Dpws client to wcf web-service

Gus, I did find that a previous issue I was having (UDP simply stopped sending in a Syslog sender I wrote) was fixed with the latest firmware/SDK.

The exception in this use case is getting thrown in one of the four socketopt calls and within the following code (looking at the 4.2 source tree). I am going to take this code and run by itself, and see what results I get–will report back shortly.

        /// <summary>
        /// Opens the stream for the UDP tansport binding 
        /// </summary>
        /// <param name="stream">The stream for this binding.</param>
        /// <param name="ctx">The context associated with the stream for this binding.</param>
        /// <returns>The handling status for this operation.</returns>
        protected override ChainResult OnOpen( ref Stream stream, BindingContext ctx )
        {
            m_udpReceiveClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPEndPoint localEP = new IPEndPoint(s_localIP, m_config.DiscoveryPort);
            m_udpReceiveClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            m_udpReceiveClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, 0x5000);

            // Join Multicast Group
            byte[] discoveryAddr = m_config.DiscoveryAddress.GetAddressBytes();
            byte[] ipAddr        = s_localIP.GetAddressBytes();
            byte[] multicastOpt  = new byte[] {  discoveryAddr[0], discoveryAddr[1], discoveryAddr[2], discoveryAddr[3],   // WsDiscovery Multicast Address: 239.255.255.250
                                                 ipAddr       [0], ipAddr       [1], ipAddr       [2], ipAddr       [3] }; // Local IPAddress
            m_udpReceiveClient.Bind(localEP);
            m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, ipAddr );
            m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOpt);

            return ChainResult.Continue;
        }

OK, here’s the repro code. I followed the stack call all the way through the NET MF 4.2 source and the only basic difference is the use of the WSDiscovery multicast address of 239.255.255.250, and I used IPAddrAny. I have chosen to use the accepted (private) administrative multicast address in the repro code. I get the same exception as in the WS code.

        public static Gadgeteer.Modules.GHIElectronics.Ethernet_J11D eth0;

        public static void Main()
        {
            Mainboard = new GHIElectronics.Gadgeteer.FEZSpider();
            Program program = new Program();
            eth0 = new Gadgeteer.Modules.GHIElectronics.Ethernet_J11D(7);

            program.BugRepro();
        }

        public void BugRepro()
        {
            Program.eth0.UseThisNetworkInterface();
            Program.eth0.UseStaticIP("192.168.0.80", "255.255.255.0", "192.168.0.1");

            IPAddress anyIPAddr = IPAddress.Any;
            IPEndPoint endPoint = new IPEndPoint(anyIPAddr, 9000);
            System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
            socket.Bind(endPoint);

            byte[] discoveryAddr = IPAddress.Parse("239.0.0.10").GetAddressBytes();  // administratively scoped IPv4 multicast address
            byte[] ipAddr = IPAddress.Any.GetAddressBytes();

            byte[] multicastOpt = new byte[] {  discoveryAddr[0], discoveryAddr[1], discoveryAddr[2], discoveryAddr[3],   // WsDiscovery Multicast Address: 239.255.255.250
                                                 ipAddr       [0], ipAddr       [1], ipAddr       [2], ipAddr       [3] }; // Local IPAddress

            socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOpt);
        }

Not sire if multicast was tested but the bug we had was related to the hardware driver not the TCP/IP stack. If we can locate a problem with the stack then we can try to track it down and probably involve Microsoft as this may effect all devices.

Gus, a little digging in the NETMF sockets layer and I found the following content buried in the socket options source:

    ///    <para>
    ///       IP multicast interface.
    ///       - Additional comments by mbolien:
    ///         multicast interface  You provide it with an SOCKADDR_IN, and that tells the
    ///         system that it should receive multicast messages on that interface (if you
    ///         have more than one interface).  Binding the socket is not sufficient, since
    ///         if the Ethernet hardware isnt set up to grab the multicast packets, it wont
    ///         do good to bind the socket.  Kinda like raw sockets.  Unless you
    ///         put the Ethernet card in promiscuous mode, youll only get stuff sent to and
    ///         from your machine.
    ///    </para>

Can you verify if the Ethernet driver for the J11D is supporting a promiscuous mode for multicast support? If not, honestly not sure how we get DPWS working if the underlying framework is requiring setting up a UDP multicast session first and if in fact, according to this comment, the Ethernet hardware must be able to support promiscuous?

Nice digging Chris.

@ Gus BTW the error actually occurs in Microsoft.SPOT.Net.SocketNative. I stepped through the source code but can go no further into the workings.

I also took a look at the 4.1 DPWS client and the code has not changed in this area, the exact same call is made successfully. i.e.

m_udpReceiveClient.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOpt);

Didn’t GHI enable multiple IP stacks in the 4.2 release? if so I am wondering if the issue is caused by the socket not being bound to a local IP address. I know that with 4.1 UDP multicast greeting messages work in the emulator but not on the spider due to the Send socket not being bound (http://www.tinyclr.com/forum/topic?id=2057&page=2).

My thinking is that with the single IP stack, not binding the receive socket may be ok but with multiple interfaces, the lack of binding could cause the 10049 error as described here: sending UDP packet from microcontroller, binding problems

http://www.tinyclr.com/forum/topic?id=2057&page=1

We will investigate.

OK, verdict in–works on the emulator.

Here’s the test code for anyone wanting to jump back and forth and test for themselves:

        public static void Main()
        {
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 9050);
            System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.Bind(endPoint);

            byte[] discoveryAddr = IPAddress.Parse("239.255.255.250").GetAddressBytes();  // administratively scoped IPv4 multicast address
            byte[] ipAddr = null;

            //
            // Add these lines to test on the FEZSpider board with Ethernet_J11D; comment them out
            // to run this code on the emulator
            //

            /*
            Mainboard = new GHIElectronics.Gadgeteer.FEZSpider();
            Gadgeteer.Modules.GHIElectronics.Ethernet_J11D eth0 = new Gadgeteer.Modules.GHIElectronics.Ethernet_J11D(7);
            eth0.UseThisNetworkInterface();
            eth0.UseStaticIP("192.168.0.146", "255.255.255.0", "192.168.0.1");  // obviously adjust for your network
            */

            NetworkInterface[] inets = Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface n in inets)
            {
                if (n.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
                {
                    if (n.IPAddress != "0.0.0.0" &&
                        n.IPAddress.Substring(0,3)!="169")
                    {
                        ipAddr = IPAddress.Parse(n.IPAddress).GetAddressBytes();

                        byte[] multicastOpt = new byte[] {  discoveryAddr[0], discoveryAddr[1], discoveryAddr[2], discoveryAddr[3], 
                                                ipAddr  [0], ipAddr  [1], ipAddr  [2], ipAddr  [3] };

                        // 
                        // Throws exception on NETMF 4.2, Spider and Ethernet_J11D (GHI February SDK Update)
                        //
                        socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multicastOpt);
                    }
                }
            }
        }

Now, as much as I can gather looking at the source, the impact to DPWS if one wanted to catch the exception and carry on:

  1. The exception is thrown about half way through the Device start up code
  2. The DPWS “Hello” message will not get sent
  3. The event manager will not get initialized

Would be nice to get this one working–thanks!

To confirm the sample code throws the exact same error on the Mountaineer Ethernet board :frowning:

Gus, any ETA on getting this resolved? DPWS is useless right now until.

It is on the list but no ETA just yet.

Do you have a ETA yet? And will it be fixed for the Mountaineer Ethernet aswell?

Any day now. This fix is on GHI premium devices only for now. But I am not sure if low memory devices can run DPWS, haven’t tried it.

Low memory devices e.g. mountaineer do not have the xmlreader class implemented; DPWS needs this class.so no.

For Mountaineer I built a version of DPWS server that uses my own leightweight xml reader and has no discovery service ; it works great. Once the udp issue is fixed I plan to add discovery, memory permitting

Btw, we added XML to cerberus on SDK coming this week.

The new SDK from April fixes DPWS discovery.

Is there a new SDK for mountaineer in the works ?