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();
            }
        }
        //--//

        public DpwsDiscoClientService(DpwsClient client, ProtocolVersion version)
        {
            m_client = client;
            m_threadLock = new object();
            m_version = version;

            m_messageCheck = new WsMessageCheck();

            // Add discovery Hello ServiceOperations
            m_discoCallbacks = new WsServiceOperations();
            m_discoCallbacks.Add(new WsServiceOperation(m_version.DiscoveryNamespace, "Hello"));
            m_discoCallbacks.Add(new WsServiceOperation(m_version.DiscoveryNamespace, "Bye"));
        }
        /// <summary>
        /// Parses a ResolveMatches message.
        /// </summary>
        /// <param name="resolveResponse">A byte array containing a resolve response soap message.</param>
        /// <param name="messageID">
        /// A string containing the message ID of the original request. This is used to make insure this is
        /// a response to the original request.
        /// </param>
        /// <param name="remoteEP">
        /// A IPEndPoint containing the remote address of the service that sent this response.
        /// </param>
        /// <param name="messageCheck">
        /// A WsdMessageCheck object ued to test for a duplicate request message.
        /// If null no check is performed as would be the case for a directed probe response.
        /// </param>
        /// <returns>
        /// A DpwsResolveMatch object containing a service endpoint description returned by a service.
        /// </returns>
        /// <exception cref="XmlException">If required tags are missing or invalid namespaces are detected.</exception>
        public DpwsServiceDescription ProcessResolveMatch(WsMessage resolveResponse, string messageID, IPEndPoint remoteEP, WsMessageCheck messageCheck)
        {
            DpwsServiceDescriptions resolveMatches = ProcessMatch(DpwsServiceDescription.ServiceDescriptionType.ResolveMatch, resolveResponse, messageID, remoteEP, messageCheck);

            return (resolveMatches == null ? null : resolveMatches[0]);
        }
 /// <summary>
 /// Parses a ProbeMatches message.
 /// </summary>
 /// <param name="probeResponse">A byte array containing a probe response soap message.</param>
 /// <param name="messageID">
 /// A string containing the message ID of the original request. This is used to make insure this is
 /// a response to the original request.
 /// </param>
 /// <param name="remoteEP">
 /// A IPEndPoint containing the remote address of the service that sent this response.
 /// </param>
 /// <param name="messageCheck">
 /// A WsMessageCheck object ued to test for a duplicate request message.
 /// If null no check is performed as would be the case for a directed probe response.
 /// </param>
 /// <returns>
 /// A DpwsProbeMatch object containing a service endpoint description returned by a service.
 /// </returns>
 /// <exception cref="XmlException">If required tags are missing or invalid namespaces are detected.</exception>
 public DpwsServiceDescriptions ProcessProbeMatch(WsMessage probeResponse, string messageID, IPEndPoint remoteEP, WsMessageCheck messageCheck)
 {
     return ProcessMatch(DpwsServiceDescription.ServiceDescriptionType.ProbeMatch, probeResponse, messageID, remoteEP, messageCheck);
 }
示例#5
0
        /// <summary>
        /// Listens for Udp request on 239.255.255.250:3702
        /// </summary>
        /// <remarks>On initialization it sends a Discovery Hello message and listens on the Ws-Discovery
        /// endpoint for a request. When a request arrives it starts a UdpProcess thread that processes the message.
        /// The number of UdpProcessing threads are limited by the Device.MaxUdpRequestThreads property.
        /// </remarks>
        private void Listen()
        {
            // Create a duplicate message tester.
            WsMessageCheck messageCheck = new WsMessageCheck(40);

            while (!m_requestStop)
            {
                try
                {
                    // If threads ara availble receive next message. If we are waiting on threads let the socket
                    // buffer request until we get a thread. This will work until the reveice buffer is depleted
                    // at which time request will be dropped
                    if (m_threadManager.ThreadsAvailable == true)
                    {
                        RequestContext req = m_replyChannel.ReceiveRequest();

                        if (req != null)
                        {
                            WsWsaHeader header = req.Message.Header;

                            if (header.MessageID != null &&
                                messageCheck.IsDuplicate(header.MessageID,header.From != null ? header.From.Address.AbsoluteUri : ""))
                            {
                                continue;
                            }

                            // Try to get a processing thread and process the request
                            m_threadManager.StartNewThread(new WsUdpMessageProcessor(m_serviceEndpoints, req));
                        }
                        else
                        {
                            System.Ext.Console.Write("UDP Receive returned 0 bytes");
                        }
                        
                    }
                    else
                    {
                        System.Ext.Console.Write("Udp service host waiting for a thread...");

                        m_threadManager.ThreadEvent.WaitOne();
                    }
                }
                catch (SocketException se)
                {
                    // Since the MF Socket does not have IOControl that would be used to turn off ICMP notifications
                    // for UDP, catch 10054 and try to continue
                    if ((SocketError)se.ErrorCode == SocketError.ConnectionReset)
                    {
                        Thread.Sleep(100);
                    }
                }
                catch (Exception e)
                {
                    System.Ext.Console.Write(e.Message + " " + e.InnerException);
                }
            }
        }
        /// <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;
        }
示例#8
0
        /// <summary>
        /// Listens for Udp request on 239.255.255.250:3702
        /// </summary>
        /// <remarks>On initialization it sends a Discovery Hello message and listens on the Ws-Discovery
        /// endpoint for a request. When a request arrives it starts a UdpProcess thread that processes the message.
        /// The number of UdpProcessing threads are limited by the Device.MaxUdpRequestThreads property.
        /// </remarks>
        public void Listen()
        {
            // Create a duplicate message tester.
            WsMessageCheck messageCheck = new WsMessageCheck(40);

            // Create remote endpoint reference, start listening
            byte[] buffer = new byte[c_MaxUdpPacketSize];
            int size;
            bool threadPoolDepletedFlag = false;
            m_servicesRunning = !m_requestStop;
            while (!m_requestStop)
            {
                try
                {
                    // If threads ara availble receive next message. If we are waiting on threads let the socket
                    // buffer request until we get a thread. This will work until the reveice buffer is depleted
                    // at which time request will be dropped
                    if (m_threadManager.ThreadsAvailable == true)
                    {
                        threadPoolDepletedFlag = false;

                        EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);

                        size = m_udpReceiveClient.ReceiveFrom(buffer, c_MaxUdpPacketSize, SocketFlags.None, ref remoteEP);

                        // If the stack is set to ignore request from this address do so
                        if (this.IgnoreRequestFromThisIP == true &&
                            ((IPEndPoint)remoteEP).Address.ToString() == WsNetworkServices.GetLocalIPV4Address())
                        {
                            continue;
                        }

                        if (size > 0)
                        {
                            byte[] soapMessage = new byte[size];
                            Array.Copy(buffer, soapMessage, size);

                            System.Ext.Console.Write("UDP Request From: " + remoteEP.ToString());
                            System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(soapMessage)));

                            // Try to get a processing thread and process the request
                            m_threadManager.StartNewThread(new WsUdpMessageProcessor(m_serviceEndpoints, soapMessage, (IPEndPoint)remoteEP, messageCheck));
                        }
                        else
                        {
                            System.Ext.Console.Write("UDP Receive returned 0 bytes");
                        }
                    }
                    else
                    {
                        if (threadPoolDepletedFlag == false)
                        {
                            System.Ext.Console.Write("Udp service host waiting for a thread...");
                            threadPoolDepletedFlag = true;
                        }
                    }
                }
                catch (SocketException se)
                {
                    // Since the MF Socket does not have IOControl that would be used to turn off ICMP notifications
                    // for UDP, catch 10054 and try to continue
                    if (se.ErrorCode == 10054)
                        continue;
                }
                catch (Exception e)
                {
                    System.Ext.Console.Write(e.Message + " " + e.InnerException);
                }

                Thread.Sleep(100);
            }
        }
示例#9
0
 /// <summary>
 /// Creates an empty instance of the UdpProcess class.
 /// </summary>
 public WsUdpMessageProcessor(WsServiceEndpoints serviceEndpoints, byte[] soapMessage, IPEndPoint remoteEP, WsMessageCheck messageCheck)
 {
     m_serviceEndpoints = serviceEndpoints;
     m_soapMessage = soapMessage;
     m_remoteEP = remoteEP;
     m_messageCheck = messageCheck;
 }
示例#10
0
        /// <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;
        }
示例#11
0
        /// <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;
        }