Ejemplo n.º 1
0
        /// <summary>
        /// Initializes the device. This method builds the colletion of internal device services, sets
        /// the devices transport address and adds DPWS required namespaces to the devices namespace collection.
        /// </summary>
        public static void Initialize(Binding binding, ProtocolVersion v)
        {
            m_binding = binding;

            string addr  = binding.Transport.EndpointAddress.AbsoluteUri;
            int    index = addr.LastIndexOf('/');

            m_address = "urn:uuid:" + addr.Substring(index + 1);

            SubscriptionManager = new DpwsWseSubscriptionMgr(binding, v);

            if (v != null)
            {
                // Add disco services to udp service endpoints collection
                m_discoveryService = new DpwsDeviceDiscoService(v);
                m_discoGreeting    = new DpwsDiscoGreeting(v);
                // Create a new udp service host and add the discovery endpoints
                WsUdpServiceHost.Instance.AddServiceEndpoint(m_discoveryService);
            }

            // Add metadata get service endpoint
            m_discoMexService = new DpwsDeviceMexService(v);
            m_hostedServices.DiscoMexService = m_discoMexService;

            // Add direct probe service endpoint
            if (m_discoveryService != null)
            {
                m_hostedServices.Add(m_discoveryService);
            }

            // Create a new http service host and add hosted services endpoints
            m_httpServiceHost = new WsHttpServiceHost(m_binding, m_hostedServices);

            System.Ext.Console.Write("IP Address: " + WsNetworkServices.GetLocalIPV4Address());
        }
        /// <summary>
        /// Creates an instance of the UDP binding element
        /// </summary>
        /// <param name="cfg">The configuration associated with this binding element.</param>
        public UdpTransportBindingElement(UdpTransportBindingConfig cfg)
        {
            m_config = cfg;

            if (s_localIP == null)
            {
                s_localIP = IPAddress.Parse(WsNetworkServices.GetLocalIPV4Address());
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Method used to send Hello and Bye messages
        /// </summary>
        /// <param name="greetingType">An integer representing the type of greeting 0 = Hello, 1 = Bye.</param>
        public static void SendGreetingMessage(bool isHello)
        {
            // If Adhoc disco is turned off return. Adhoc disco is optional with a Discovery Proxy
            if (Device.SupressAdhoc == true)
            {
                return;
            }

            byte[] greetingsMessage = null;
            if (isHello)
            {
                greetingsMessage = BuildHelloMessage(Device.DiscoVersion.WellKnownAddress, null, null);
            }
            else
            {
                greetingsMessage = BuildByeMessage(Device.DiscoVersion.WellKnownAddress, null, null);
            }

            // Create a UdpClient used to send Hello and Bye messages
            Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

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

            if (DiscoveryEP == null)
            {
                DiscoveryEP = new IPEndPoint(new IPAddress(DiscoveryAddress), DiscoveryPort);
            }

            // Random back off implemented as per soap over udp specification
            // for unreliable multicast message exchange
            Random rand    = new Random();
            int    backoff = 0;

            for (int i = 0; i < MulticastUdpRepeat; ++i)
            {
                if (i == 0)
                {
                    backoff = rand.Next(UdpMaxDelay - UdpMinDelay) + UdpMinDelay;
                }
                else
                {
                    backoff = backoff * 2;
                    backoff = backoff > UdpUpperDelay ? UdpUpperDelay : backoff;
                }

                Thread.Sleep(backoff);
                udpClient.SendTo(greetingsMessage, greetingsMessage.Length, SocketFlags.None, DiscoveryEP);
            }

            udpClient.Close();
        }
        /// <summary>
        /// Creates an instance of the configuration for the HTTP transport
        /// </summary>
        /// <param name="serviceUrn">The service Urn.</param>
        /// <param name="port">The servce port.</param>
        public HttpTransportBindingConfig(string serviceUrn, int port)
        {
            this.ServiceUrn = new Uri(serviceUrn);

            string transport = "http://" + WsNetworkServices.GetLocalIPV4Address() + ":" + port + "/";

            if (serviceUrn.IndexOf("urn:uuid:") == 0)
            {
                this.EndpointAddress = new Uri(transport + serviceUrn.Substring(9), UriKind.Absolute); // strip off urn:uuid:
            }
            else
            {
                this.EndpointAddress = new Uri(transport + serviceUrn, UriKind.Absolute);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Processes a message
        /// </summary>
        /// <param name="stream">The message being processed.</param>
        /// <param name="ctx">The context associated with the message.</param>
        /// <returns>The handling status for this operation.</returns>
        protected override ChainResult OnProcessInputMessage(ref WsMessage msg, BindingContext ctx)
        {
            byte[] soapMessage = null;
            byte[] buffer      = new byte[MaxUdpPacketSize];

            while (true)
            {
                EndPoint remoteEndpoint = new IPEndPoint(IPAddress.Any, 0);

                int size = m_udpReceiveClient.ReceiveFrom(buffer, MaxUdpPacketSize, SocketFlags.None, ref remoteEndpoint);

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

                if (size > 0)
                {
                    soapMessage = new byte[size];
                    Array.Copy(buffer, soapMessage, size);
                }
                else
                {
                    System.Ext.Console.Write("UDP Receive returned 0 bytes");
                }

                m_remoteEndpoint = remoteEndpoint;

                break;
            }

            System.Ext.Console.Write("UDP Request From: " + m_remoteEndpoint.ToString());
            System.Ext.Console.Write(soapMessage);

            msg.Body = soapMessage;

            return(ChainResult.Continue);
        }
Ejemplo n.º 6
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();

            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);
        }
Ejemplo n.º 7
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;
            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);
        }
Ejemplo n.º 8
0
        public virtual WsMessage ProbeMatch(WsMessage probe, DpwsHostedService matchedService)
        {
            XmlReader   reader = probe.Reader;
            WsWsaHeader header = probe.Header;

            // Performance debugging
            DebugTiming timeDebuger = new DebugTiming();
            long        startTime   = timeDebuger.ResetStartTime("");

            // Build ProbeMatch
            using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                // If a Host exist write the Host namespace
                WsXmlNamespaces additionalPrefixes = null;
                if (Device.Host != null)
                {
                    additionalPrefixes = new WsXmlNamespaces();
                    additionalPrefixes.Add(Device.Host.ServiceNamespace);
                }

                WsWsaHeader matchHeader = new WsWsaHeader(
                    this.Version.DiscoveryNamespace + "/ProbeMatches", // Action
                    header.MessageID,                                  // RelatesTo
                    this.Version.AnonymousUri,                         // To
                    null, null, null);                                 // ReplyTo, From, Any

                WsMessage msg = new WsMessage(matchHeader, null, WsPrefix.Wsd | WsPrefix.Wsdp, additionalPrefixes,
                                              new WsAppSequence(Device.AppSequence, Device.SequenceID, Device.MessageID));

                WsSoapMessageWriter smw = new WsSoapMessageWriter(this.Version);
                smw.WriteSoapMessageStart(xmlWriter, msg);

                // Performance debuging
                timeDebuger.PrintElapsedTime("*****Write Header Took");

                // write body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "ProbeMatches", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "ProbeMatch", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "EndpointReference", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null);
                xmlWriter.WriteString(matchedService == null ? Device.EndpointAddress : matchedService.EndpointAddress);
                xmlWriter.WriteEndElement();
                xmlWriter.WriteEndElement();

                // Write hosted service types
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "Types", null);
                WriteDeviceServiceTypes(xmlWriter);
                xmlWriter.WriteEndElement(); // End Types

                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "XAddrs", null);

                string transport = Device.TransportAddress;
                if (matchedService != null)
                {
                    int idx = transport.LastIndexOf('/');
                    if (idx != -1)
                    {
                        transport  = transport.Substring(0, idx + 1);
                        transport += matchedService.EndpointAddress.Substring(matchedService.EndpointAddress.IndexOf("urn:uuid:") + 9);
                    }
                }

                int idx2 = transport.ToLower().IndexOf("localhost");

                if (idx2 != -1)
                {
                    transport = transport.Substring(0, idx2) + WsNetworkServices.GetLocalIPV4Address() + transport.Substring(idx2 + 9 /*localhost*/);
                }

                xmlWriter.WriteString(transport);
                xmlWriter.WriteEndElement();

                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "MetadataVersion", null);
                xmlWriter.WriteString(Device.MetadataVersion.ToString());
                xmlWriter.WriteEndElement();

                xmlWriter.WriteEndElement();
                xmlWriter.WriteEndElement();

                smw.WriteSoapMessageEnd(xmlWriter);

                msg.Body = xmlWriter.ToArray();

                // Performance debuging
                timeDebuger.PrintTotalTime(startTime, "***ProbeMatch Took");

                // Delay probe match as per Ws-Discovery specification (2.4 Protocol Assignments)
                Thread.Sleep(new Random().Next(Device.ProbeMatchDelay));

                // Return stream buffer
                return(msg);
            }
        }
Ejemplo n.º 9
0
        public virtual WsMessage ResolveMatch(WsMessage message)
        {
            XmlReader   reader = message.Reader;
            WsWsaHeader header = message.Header;
            bool        match  = false;
            string      epAddr = "";

            reader.ReadStartElement("Resolve", this.Version.DiscoveryNamespace);


            if (reader.IsStartElement("EndpointReference", this.Version.AddressingNamespace) == false)
            {
                return(null);
            }

            WsWsaEndpointRef epRef = new WsWsaEndpointRef(reader, this.Version.AddressingNamespace);

            epAddr = epRef.Address.AbsoluteUri;

            if (Device.EndpointAddress != epAddr)
            {
                // If the destination endpoint is ours send a resolve match else return null
                int servicesCount = Device.HostedServices.Count;
                DpwsHostedService hostedService;
                for (int i = 0; i < servicesCount; i++)
                {
                    hostedService = (DpwsHostedService)Device.HostedServices[i];
                    // Skip internal services
                    if (hostedService.ServiceTypeName == "Internal")
                    {
                        continue;
                    }

                    if (hostedService.EndpointAddress == epAddr)
                    {
                        match = true;
                        break;
                    }
                }

                if (!match)
                {
                    return(null);
                }
            }

            // Build ResolveMatch
            using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                // If a Host exist write the Host namespace
                WsXmlNamespaces additionalPrefixes = null;
                if (Device.Host != null)
                {
                    additionalPrefixes = new WsXmlNamespaces();
                    additionalPrefixes.Add(Device.Host.ServiceNamespace);
                }

                WsWsaHeader matchHeader = new WsWsaHeader(
                    this.Version.DiscoveryNamespace + "/ResolveMatches",  // Action
                    header.MessageID,                                     // RelatesTo
                    this.Version.AnonymousUri,                            // To
                    null, null, null);                                    // ReplyTo, From, Any

                WsMessage msg = new WsMessage(matchHeader, null, WsPrefix.Wsd | WsPrefix.Wsdp, additionalPrefixes,
                                              new WsAppSequence(Device.AppSequence, Device.SequenceID, Device.MessageID));

                WsSoapMessageWriter smw = new WsSoapMessageWriter(this.Version);
                smw.WriteSoapMessageStart(xmlWriter, msg);

                // write body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "ResolveMatches", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "ResolveMatch", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "EndpointReference", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null);
                xmlWriter.WriteString(epRef.Address.AbsoluteUri);
                xmlWriter.WriteEndElement(); // End Address
                xmlWriter.WriteEndElement(); // End EndpointReference

                // Write hosted service types
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "Types", null);
                WriteDeviceServiceTypes(xmlWriter);
                xmlWriter.WriteEndElement(); // End Types

                string transport = Device.TransportAddress;
                if (match)
                {
                    int idx = transport.LastIndexOf('/');
                    if (idx != -1)
                    {
                        transport  = transport.Substring(0, idx + 1);
                        transport += epAddr.Substring(epAddr.IndexOf("urn:uuid:") + 9);
                    }
                }

                int idx2 = transport.ToLower().IndexOf("localhost");

                if (idx2 != -1)
                {
                    transport = transport.Substring(0, idx2) + WsNetworkServices.GetLocalIPV4Address() + transport.Substring(idx2 + 9 /*localhost*/);
                }

                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "XAddrs", null);
                xmlWriter.WriteString(transport);
                xmlWriter.WriteEndElement(); // End XAddrs

                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsd, "MetadataVersion", null);
                xmlWriter.WriteString(Device.MetadataVersion.ToString());
                xmlWriter.WriteEndElement(); // End MetadataVersion

                xmlWriter.WriteEndElement(); // End ResolveMatch
                xmlWriter.WriteEndElement(); // End ResolveMatches

                smw.WriteSoapMessageEnd(xmlWriter);

                msg.Body = xmlWriter.ToArray();

                // Return stream buffer
                return(msg);
            }
        }
Ejemplo n.º 10
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);
            }
        }
        /// <summary>
        /// Method used to send Hello and Bye messages
        /// </summary>
        /// <param name="greetingType">An integer representing the type of greeting 0 = Hello, 1 = Bye.</param>
        public void SendGreetingMessage(bool isHello)
        {
            // If Adhoc disco is turned off return. Adhoc disco is optional with a Discovery Proxy
            if (Device.SupressAdhoc == true)
            {
                return;
            }

            WsMessage greetingsMessage = null;

            if (isHello)
            {
                greetingsMessage = BuildHelloMessage(Device.DiscoveryVersion.DiscoveryWellKnownAddress, null, null);
            }
            else
            {
                greetingsMessage = BuildByeMessage(Device.DiscoveryVersion.DiscoveryWellKnownAddress, null, null);
            }

            byte[] greeting = (byte[])greetingsMessage.Body;

            System.Ext.Console.Write("UDP (" + (isHello ? "Hello" : "Bye") + ") multicast to: " + WsDiscovery.WsDiscoveryEndPoint.ToString());
            System.Ext.Console.Write(greetingsMessage.Body as byte[]);

            // Create a UdpClient used to send Hello and Bye messages
            using (Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
            {
                // Very important - Set default multicast interface for the underlying socket
                udpClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)WsNetworkServices.GetLocalIPV4AddressValue());

                // Random back off implemented as per soap over udp specification
                // for unreliable multicast message exchange
                Random rand    = new Random();
                int    backoff = 0;
                for (int i = 0; i < MulticastUdpRepeat; ++i)
                {
                    if (i == 0)
                    {
                        backoff = rand.Next(UdpMaxDelay - UdpMinDelay) + UdpMinDelay;
                    }
                    else
                    {
                        backoff = backoff * 2;
                        backoff = backoff > UdpUpperDelay ? UdpUpperDelay : backoff;
                    }

                    udpClient.SendTo(greeting, greeting.Length, SocketFlags.None, WsDiscovery.WsDiscoveryEndPoint);
                    Thread.Sleep(backoff);
                }
            }
        }
        /// <summary>
        /// UDP resend timer callback.  Resends repsonse data for UDP messages.
        /// </summary>
        /// <param name="arg"></param>
        static private void UdpTimer(object arg)
        {
            int cnt;

            UdpResend[] resend = null;

            // get a copy of the resend list so that we don't have to lock the list
            // while we resend
            lock (s_repeats)
            {
                cnt = s_repeats.Count;
                if (cnt > 0)
                {
                    resend = (UdpResend[])s_repeats.ToArray(typeof(UdpResend));
                }
                else
                {
                    s_udpTimer.Change(-1, -1);
                }
            }

            if (cnt > 0)
            {
                using (Socket udpSendClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
                {
                    IPEndPoint localEP = new IPEndPoint(s_localIP, 0);
                    udpSendClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)WsNetworkServices.GetLocalIPV4AddressValue());
                    udpSendClient.Bind(localEP);

                    for (int i = cnt - 1; i >= 0; i--)
                    {
                        udpSendClient.SendTo(resend[i].Data, resend[i].Data.Length, SocketFlags.None, resend[i].RemoteEndpoint);

                        if (0 >= --((UdpResend)s_repeats[i]).RepeatCount)
                        {
                            s_repeats.RemoveAt(i);
                        }
                    }
                }
            }
        }
Ejemplo n.º 13
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);
        }
Ejemplo n.º 14
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);
        }