A class to configure the network parameters from an HTTP page

Crazy early spring thunderstorms here this morning, so I shut everything down before running out the door to work…

@ Nicolas3 - to answer an earlier question, i’m using a static IP, so DCHP is not a factor. Also, I don’t use NetBios. That protocol just won’t go away ???

Ok, we’ve got the same thunderstorms this morning as well, we are not that far away :wink:

As for the netbios, even if it’s old and crapy, I find it very useful to connect to a device when you don’t know its IP adress. For an example, if I make a profesionnal “box” using netconfig (which I intend to do someday !), it will be delivered with default configuration, that will use DHCP only to be easily “plug and play” by the customer. So either you have an LCD screen to show what IP you got, or in the documentation you just tell the customer to log into http://yourdefaultdevicename to complete the configuration. It is very usefull as a startup name lookup. All computers undertstand this protocol… However, the full netbios stack shall be deprecated… My implementation of the protocol is minimal (only name lookups !).

My primary aim at making the netconfig framework is to actualy make a product I can sell, using the less possible expensive hardware to attrack the customer, so I can actually make money out of the service I am providing with it :smiley: So it shall be as simple as possible, and I’m not too regarding to what is technicaly overdated or not, I just want it to work :whistle: !

Cheers,
Nicolas

Nicolas3,

I downloaded the code. Do you have a simpler code that only shows the problem?
The code is very neat by the way. :wink:

Joe

Joe,

Not right now. I have only one board running a longggggggg test at the moment. These kind of problem are a pain because it takes so long between 2 tests ! As soon as this one hangs, I’ll try to make up one. ::slight_smile:

On your side, can you confirm that the simple server code like the one you told us about last week can work many days in a row without hanging ? http://www.tinyclr.com/forum/2/2911/

Joe,

I am having similar behavior with the following very simple http server:


using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Net;
using GHIElectronics.NETMF.Net;
using GHIElectronics.NETMF.Net.Sockets;
using GHIElectronics.NETMF.Net.NetworkInformation;

using System.Text;
using Socket = GHIElectronics.NETMF.Net.Sockets.Socket;

namespace TestHttp
{
    public class Program
    {
        public static void Main()
        {
            // Configure Network
            WIZnet_W5100.Enable(SPI.SPI_module.SPI1, 
                               (Cpu.Pin)FEZ_Pin.Digital.Di10, 
                               (Cpu.Pin)FEZ_Pin.Digital.Di9, 
                               true);
            NetworkInterface.EnableStaticIP(new byte[] { 192, 168, 0, 12 }, 
                                            new byte[] { 255, 255, 255, 0 }, 
                                            new byte[] { 192, 168, 0, 1 }, 
                                            new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA });
            NetworkInterface.EnableStaticDns(new byte[] { 192, 168, 0, 1 });

            // Configure HTTP server
            HttpListener Listener = new HttpListener("http", 80);
            Listener.Start();
            byte[] Page = Encoding.UTF8.GetBytes("<html><body>Hello, World !</body></html>");

            while (true)
            {
                HttpListenerContext ctx = Listener.GetContext();
                Debug.Print("Serving a page...");
                ctx.Response.ContentLength64 = Page.Length;
                ctx.Response.ContentType = "text/html";
                ctx.Response.OutputStream.Write(Page, 0, Page.Length);
                ctx.Response.Close();
                ctx.Close();
                Debug.GC(true);
                Debug.Print("Done with the page.");
            }

        }

    }
}

After several hours and many pages sent, I get the following error at the line “ctx.Response.ContentLength64 = Page.Length;” :

Serving a page…
#### Exception System.NullReferenceException - CLR_E_NULL_REFERENCE (1) ####
#### Message:
#### TestHttp.Program::Main [IP: 007f] ####
A first chance exception of type ‘System.NullReferenceException’ occurred in TestHttp.exe
An unhandled exception of type ‘System.NullReferenceException’ occurred in TestHttp.exe

Uncaught exception

I am not sure exactly why. I shall maybe take the Response object out of the Context object. I’ll try…

I am running the HTTP server as you suggested. it is been on for 48hr so far and I tried to access it every few hours and it worked fine. I am afraid that is something related to your Ethernet switch/router.

Did you try it with a safe MAC address?
Dave suggested this website that generates safe MAC addresses. I was having a problem having FEZ connect communicating with one of the networking devices and it worked after I used a safe MAC address
Dave:
[url]http://www.tinyclr.com/forum/2/2946/#/2/[/url]

[quote]Most switches and routers will have a problem if the first octet of the mac address is “ODD” or has the least significant bit set to “1”. This is used to indicate a MAC Multi cast. see MAC address - Wikipedia .

Here is the tool I use to create “Safe” mac addresses. http://www.macvendorlookup.com/ as long as you are on you own lan segment you can use any of the addresses it generates, just DON’T use the same MAC on other devices on the same LAN segment. [/quote]

I will try the code you posted tomorrow.

When I created my webserver class, I detected that I needed to use try/catch around it. Sometimes the remote connection gets lost or closed before you can send a response. In such situations accessing the response object throws an exception.

Do a test: request your webpage, then hit F5 to refresh the page multiple times as fast as you can. You should get an exception.

Thank you all, your help is really valuable and appreciated :slight_smile:

Working on hardening the class.
Looks like the Wiz5100 HttpListener class can be somewhat tricky to use;
For an example, contrary to the microsoft NETMF sample and Wouter’s Fez Cobra great http server, you absolutely need to Close() the context after closing the response, if not you get big memory leaks if your page was sent in several cheaks. Contrary to some other examples found for netmf (netduino), you should never Close() the Outputstream(). Etc !

But hopefully, with all your help, I should be able to produce something stable soon !

Beta6: http://opensource.grisambre.net/fez/NetConfig.zip

Updates :

  • tentatively hardened version (running…)
  • Code updated for new SDK 1.0.14 (customizable dhcp hostname)
  • some clean up

I begin to be desperate with that http server !
Here is the code. I do not understand WHAT can fail. Any possible error is catched and recovered. This time it failed after 15 hours. I see the problem more often if I use Chrome instead of FF.

At some point, it just produces the following error, and stops responding…
This is the line that send the error : response = ctx.Response;

But it is cleanly catched ! The “continue;” here should just make it go back waiting for another call again after cleaning everything, but then it’s not accepting anything anymore, even if the Listener.IsListening is true !

catch
                    {
                        try { if (ctx != null) ctx.Close(); }
                        catch { }
                        continue;
                    }

I really begin to feel that there is a problem in the firmware !

Full server code here:


private void HttpServer()
        {
            while (true)
            {
                while (true) // Loop until the HTTP server is initialized
                {
                    // If already existing somewhere, kill it
                    try { if (Listener != null) Listener.Abort(); } 
                    catch { }
                    try // Try to init it
                    {
                        Listener = new HttpListener("http", int.Parse(GetParam("TCP")));
                        Listener.Start();
                        break;
                    }
                    catch { Debug.Print("NetConfig : Error initializing HTTP server, will retry in 30s"); }
                    Thread.Sleep(30000);
                }
                UsedSockets++;
                Debug.Print("NetConfig : HTTP Server now listening on " + MyLanUrl());

                while ((Listener!=null) && Listener.IsListening) // Answer requests
                {
                    HttpListenerResponse response = null;
                    HttpListenerContext ctx = null;
                    HttpListenerRequest request = null;
                    string Url = String.Empty;
                    bool Found;
                    Debug.GC(true);

                    try
                    {
                        ctx = Listener.GetContext();
                        response = ctx.Response;
                        request = ctx.Request;
                    }
                    catch
                    {
                        try { if (ctx != null) ctx.Close(); }
                        catch { }
                        continue;
                    }

                    UsedSockets++;
                    try
                    { 
                        Url = request.RawUrl.IndexOf('?') > 0 ? request.RawUrl.Substring(0, request.RawUrl.IndexOf('?')) : request.RawUrl;
                        Found = false;
                        foreach (Dispatcher MyD in DispatchList)
                            if (MyD.Request == Url)
                            {
                                MyD.Process(ctx, this);
                                Debug.GC(true);
                                Found = true;
                                break;
                            }
                        if (!Found)
                        {
                            byte[] b = Encoding.UTF8.GetBytes(Http404);
                            response = ctx.Response;
                            response.ContentLength64 = b.Length;
                            response.StatusCode = (int)HttpStatusCode.NotFound;
                            response.ContentType = "text/html";
                            response.OutputStream.Write(b, 0, b.Length);
                        }
                        if (response != null) response.Close();
                        if (ctx != null) ctx.Close();     
                    }
                    catch
                    {
                        try { if (response != null) response.Close(); }
                        catch { }
                        try { if (ctx != null) ctx.Close(); }
                        catch { }
                    }
                    UsedSockets--;
                }
            }
        }

I don’t know how to handle it cleanly. If any one has an advice, I take it…
Instead of the “continue;” I will now try to make a “break;” which will make the full listener to be killed and started over. To see if that clears the problem… But this is a dirty trick ! :-[

I am still strugling with making something stable :wall:. Here is the behavior I have:

  • Whenever I get an exception, it seems now properly recovered.
  • After several hours and a new incoming connection, without getting any exceptions, the IP stack simply stops accepting packets. It is just deaf to it (regular socket or httplistener). Reinitializing the HttpListener class does not help. Renewing DHCP just hangs the program (dhcp.renew becomes blocking and does not timeout / return to the program). After calling a dhcp.renew it even stops threading (still getting GC dumps via debug, though).
  • However in such situation, WIZnet_W5100.ReintializeNetworking() revovers everything.

Since I am the only one seeming to experience this problem, I begin to think of an SPI communication problem between my domino and my Wiz5100 board. Maybe a faulty network board on my side ? Maybe the IP stack just loses sync with the WIZ5100 and cannot sync again ? The wiz5100 chip is warm, but not hot. Not sure it means anything. I would be happy to find a way to “ping” the Wiz5100 to see when it’s not answerring to be able to reset it, but I don’t think it is possible ?

I will order a fez connect tonight and hope it comes fast… :wink:

I am updating the link to beta7 http://opensource.grisambre.net/fez/NetConfig.zip
I would be glad to know if the http server is still freezing after sometimes (it shouldn’t). If it does and the LED monitoring led is wired, disconnecting (waiting 30s) and reconnecting should resync.

I haven’t had time to put this on a board, I’ll try to do so for you and let it run for a while.

I have my proto-board (with wiz812MJ) set up with the link led wired to a header, so I should just have to link that over to the Fez.

Wiz always gets hot, that’s a known thing running an Ethernet MAC/PHY so don’t let that worry you :slight_smile:

On the PING aspect, have you tried doing PING from a remote PC to see if the board stops responding to ICMP packets? Basically once you start the board with an IP address it should start responding to PINGs, and perhaps that changes after a while?

I’ll be trying this on a Panda, my Domino is still out on loan.

On a side note, did anyone see that WIZ5200 was announced recently, still SPI connected, but with 8 sockets and IIRC higher SPI speed. Nice ! :slight_smile:

@ Brett,

  • Yes, the WIZ5100 board can be pinged from the outside while it appears “locked” from the domino. That’s why I think it’s a sync problem between the ip stack and the board. If it’s still powered, you can just disconnect completly the ethernet shield from th fez, it will still be pingable I think (the icmp is handled internaly) !
  • When I say ping, it could be a non ip ping, just send some data to the board and get some answer to be able to know if it’s communicating well. Of course maybe I could do instead a tcp connect to my own http server to see if it’s replying. Not sure if you can connect to yourself with the Wiz (will try !).

Thank you very much for your help ! :smiley:

I vote for the FEZ CONNECT II with 8 sockets :wink:

Yep an ICMP PING is handled by the Wiznet chip itself, it shows that the IP stack on the chip still appears to be functioning. That to me points out that this is most likely a programming issue - whether it’s yours or Joe@ GHI’s I am not taking bets on :slight_smile: :wink: ;D

I do really think I may have an HW problem (either domino or ethernet shield).
Now it doesn’t last more than 2 hours before crashing (really crashing : even the ping in MFDEPLOY stops to answer). Even if I have a programming error, that should never crash the board (it is managed code, right ? :wink: )

Thank you GHI for already shipping my yesterday night order, that was quick !

BTW, I upgraded the code to beta8. Just corrected a typo not reinitializing the board if you use static ip address… ::slight_smile:

8? It already has 8!

Nick’s orders are special, they always ship first :slight_smile:

Great, Yes, 8 JST connector sockets !
If you add the 4 IP sockets, you can even sum them to a nice 12 :smiley: !

Funny, I am thinking JST sockets and you are talking about TCP sockets!! I must be really tired!

[quote]On a side note, did anyone see that WIZ5200 was announced recently, still SPI connected, but with 8 sockets and IIRC higher SPI speed. Nice !
[/quote]
I like that

The WIZ5200 (48 pins QFN) is however not pin compatible with 5100 (80 pin QFP).
The cost is still unknown but should be about the same price as the 5300 (already 8 sockets, but no SPI), for about 1$ more each.
The software and registers seem similar to the 5100, with little enhancements (like there is now a register to read the cable connection status…). It should be easy to adapt the software side… :wink:

I would be happy to help if GHI want to test that !