HTTP Server

19 Nov 2009

Hi Ilya,

 

Ilya I wrote:
1. How would one program "try DHCP, fallback to a given IP settings" use case?

I did not think of this might be a good feature for the next version.

 

Ilya I wrote:
2. What time units is timeout (both in HTTPClient, HTTPServer)?

timeout is in ms. I will add that in the API docs.

 

Ilya I wrote:
3. Does the latest version solve issues around lwIP bug and connection problems? With earlier version I experienced that only Firefox was opening pages from HTTPServer, and other browsers failed (Google chrome on PC, Safari on iPhone). Can't check new version for few days.

Yes, this was the main reason I've done it. But I'm sure there are many more bugs ;-) And that means I need help to find them :-D

 

Cheers

Rolf

 

 

 

25 Nov 2009

Well, the bug seemed to stay for Google Chrome. However, when I added favicon.ico, it immediately resolved the problem. I don't think it is a robust solution though. GC does not break on all other websites without favicon.

Before favicon.ico Google Chrome failed miserably - it could get first response (index.htm) and rpc can work while the first page still loads, but once the page is done loading, nothing else works, even reload of the page. At the same time Firefox keeps working OK, even while Google Chrome is struggling with the page and rpc calls.

I think it has something to do with missing favicon.ico not reported properly. I did check headers and they seem ok (RESPONSE contains "HTTP/1.1 404 Not Found"), so I checked further the page source:

<html> 
<header> 
<title>File not found<title> 
</header> 
<body> 
<h1>HTTP 404</h1> 
<p>The file you requested was not found on this mbed. </p> 
</body> 
</html> 

First thing that jumps out is <header> instead of <head>. Maybe it is the culprit?

25 Nov 2009

Ilya,

Thanks for digging,

this looks like I've made a typo. I will fix that in the next commit.

 

Regards

Rolf

25 Nov 2009

To add some more data points to this thread:

I've been trying to get the HTTPServer working but not having much luck - using Firefox, IE and Safari I cannot get a page served unless I put a delay in the while(1) loop.

wait_ms(10); was sufficient to make it work.

Without the delay in the while loop, the mbed always picked up an IP address correctly via DHCP (confirmed from my router admin pages and on the mbed serial terminal), but a page request would never complete. Pinging the mbed was always successful.

Before adding the delay to the while loop I tried adding a favicon.ico file on the mbed drive, but that made no difference. Only the delay in the while loop makes it work.

I'm using mbed rev 18 and lwiptrunk rev 655.

I'm also using the quick-n-dirty method to connect to the router - a patch cable cut in half.

Cheers,

Dan

 

26 Nov 2009

Hi Dan,

thanks for the report, I think we've seen that before. It's pretty weired but I suspect some internal lwip code handles timeout as a increasing number of walk troughs. In the description to the handler which are called by the poll function is written they should be called all 250ms. As I started to port this library I tried do do that in a timer, but I've found out that it is not working very well caused by the fact that a timer function is executed in an interrupt and mbed does not allow nested interrupts.

Furthermore I've searched for a way to make make a transfer to the client quicker and in a given environment the best way to do that is to execute the poll function more often. But unfortunately if you poll a way to often you always run into timeouts.

I was thinking about counting the time from the last call in the function and just return if the function is called to early but that would mean you would lose the skew to fine tune the speed oft your lwip stack.

So for the moment I think it is best to call wait_ms(10 - 250) whatever works in your setup best and is fast enough for you.

I should probably mention that in the documentation, and fix the examples.

 

Cheers

Rolf

27 Nov 2009

Hi Rolf,

Back to 404/favicon issue: I think it is not only <header> typo but there are more problems around 404 response:

  • Looks like Content-Length should be 164 (not 163 - there is an extra space at one line), and after fixing <header> to <head> length should be 160 (please re-check me!).
  • I fixed the above in my sandbox and missing favicon case gets a little better, but there is still a problem. I was able to narrow it down to these steps (in either in Firefox and Google Chrome) which cause interesting fault:
    0. make sure index.htm and favicon.ico exist on mbed, and HTTPServer code is running
    1. ask for existing index.htm in a browser
    2. - the page is served OK
    3. ask for a missing file in a browser (say notfound.htm)
    4. - expected 404 response for a missing file is served OK
    5. ask for an existing file (index.htm, favicon.ico) again
    6. instead of the expected page I am getting 404 response!
    7. After awhile (1 minute or so) 404 response clears and the page is served OK again

    I inserted printf("NOT FOUND %s\r\n", _request_url); to the 404 response code (HTTPServer.cpp line 180), and I'm seeing "NOT FOUND /index.htm" in the terminal while I'm doing step 6. It means that HTTPServer actually returns 404 response and it is not due to some browser-side problems, like caching.

 

While I'm at it, there is one more issue I noticed with the latest HTTPServer that I wanted to bring up:

The call to HTTPServer.bind() takes few seconds, perhaps to do DHCP. If cable is unplugged, bind() hangs (or maybe it just takes very long time, way longer than I'm willing to wait). I think it should detect if there is no physical cable connection and return, leaving DHCP for later.

27 Nov 2009

Hi Rolf,

I was puzzled by your comment

As I started to port this library I tried do do that in a timer, but I've found out that it is not working very well caused by the fact that a timer function is executed in an interrupt and mbed does not allow nested interrupts.

Could you explain why? I thought one of the big features of Cortex was the Nested Vectored Interrupt Controller.

Paul

27 Nov 2009 . Edited: 27 Nov 2009

Hi Ilya,

thanks for that closer look,

Ilya I wrote:
Looks like Content-Length should be 164 (not 163 - there is an extra space at one line), and after fixing to length should be 160 (please re-check me!).

If checked before you and your right, I've found that as well ;-)

Ilya I wrote:
I fixed the above in my sandbox and missing favicon case gets a little better, but there is still a problem. I was able to narrow it down to these steps (in either in Firefox and Google Chrome) which cause interesting fault

I did not see that one, but I will try to reproduce it. Thanks for the reproduction instructions.

Ilya I wrote:
The call to HTTPServer.bind() takes few seconds, perhaps to do DHCP. If cable is unplugged, bind() hangs (or maybe it just takes very long time, way longer than I'm willing to wait). I think it should detect if there is no physical cable connection and return, leaving DHCP for later

Well yes, that's true. It's caused by the lwip startup sequence. bind brings up the lwip stack and waits for it to continue. I was fiddling around with it a lot the last days and changed that as well to use a timeout.

 

Cheers
Rolf

 

27 Nov 2009

Hi Paul,

 

Paul Griffith wrote:
Could you explain why? I thought one of the big features of Cortex was the Nested Vectored Interrupt Controller.

No I can't, but I guess it's caused by the pain of implementing nested interrupts and the history of mbed with an ARM7 device.

 

Cheers

Rolf

 

27 Nov 2009 . Edited: 27 Nov 2009

Hi Paul,

Cortex-M3 does certainly feature nested interrupts, and in a really slick way! But the older ARM7 version is not quite as neat, and combined with the stack model the way we implemented some of the code on that to unify the stacks meant we didn't support nested interrupts on the first ARM7 version.

But now we have the M3 version, I want to try and align them more so will plan to improve the interrupt/nesting/priority support - I just want to do it in a unified way so you don't have to think about when coding. You'll notice people are sharing mbed code whether it is on ARM7 or Cortex-M3, and not having to think too much. Interrupts are an area i'd especially like this to continue to be the case (even though M3 will be much more efficient).

More when we plan it out. btw, you can always go in and fiddle directly with the VIC on the M3 if you want; all the ARM LPC1768 CMSIS functions are available.

Simon

10 Dec 2009

Hi All,

I'm trying to get the HTTP server example working on my LPC2368 mbed without any success so far. I have a simple index.htm file in the mbed drive. I have tried the pre-compiled code at http://mbed.org/projects/cookbook/svn/EMAC/lwip/examples/HTTPServer_LPC2368.bin and have tried compiling the the source at http://mbed.org/projects/cookbook/svn/EMAC/lwip/examples/HTTPServer with a little pintf at the start of main() for testing.

My set-up has the mbed on a mbed-BOB connected to my Linksys WAG200G wireless router with a crossover Ethernet cable. I get nothing from the USB serial port other than the little message I inserted in the compiled version. The router does not list an IP address for the mbed. Back in August, I successfully tried the nice Ethernet test example at http://mbed.org/projects/cookbook/wiki/EthernetTest with the same crossover Ethernet cable connected to my Windows XP PC with static IP addresses so I am pretty sure the mbed Ethernet works OK. By the way this example no longer compiles-there are heaps of errors; any idea what's changed?

Anyway, I suspect something in the router set-up is not right; I have looked over the router web pages and nothing obvious tells me why it won't DHCP the mbed. I have looked over the Forum at this and related threads and can't find any clues. I would apprecaie any help.

Thanks,

Peter

11 Dec 2009 . Edited: 14 Dec 2009

Hi Peter,

Peter Ampt wrote:

 

Hi All,

I'm trying to get the HTTP server example working on my LPC2368 mbed without any success so far. I have a simple index.htm file in the mbed drive. I have tried the pre-compiled code at http://mbed.org/projects/cookbook/svn/EMAC/lwip/examples/HTTPServer_LPC2368.bin and have tried compiling the the source at http://mbed.org/projects/cookbook/svn/EMAC/lwip/examples/HTTPServer with a little pintf at the start of main() for testing.

My set-up has the mbed on a mbed-BOB connected to my Linksys WAG200G wireless router with a crossover Ethernet cable. I get nothing from the USB serial port other than the little message I inserted in the compiled version. The router does not list an IP address for the mbed. Back in August, I successfully tried the nice Ethernet test example at http://mbed.org/projects/cookbook/wiki/EthernetTest with the same crossover Ethernet cable connected to my Windows XP PC with static IP addresses so I am pretty sure the mbed Ethernet works OK. By the way this example no longer compiles-there are heaps of errors; any idea what's changed?

Anyway, I suspect something in the router set-up is not right; I have looked over the router web pages and nothing obvious tells me why it won't DHCP the mbed. I have looked over the Forum at this and related threads and can't find any clues. I would apprecaie any help.

Thanks,

Peter

 

The old EthernetTest example was using another (older) port of lwip. It does not compile anymore with the new library because in version 12 of the mbed library changed the declaration of the pins and some other things. But on the other hand versions >11 allows you to compile for the LPC2368 and LPC1768 without rewriting your code.

The problem you have sounds like a wiring problem but this is just a guess. Can you compile and run ethersniff_hex for me and see if you can see some broadcasting packages from the network. Bets is when you make some broadcasting traffic with your pc (ARP requests or broadcast pings). You should see every arriving package with sender and receiver mac address and a hex dump of the package itself. If it works your connection is fine if not we know its a connection problem.

If it works you describe that you get stuck before you've got a IP address from your DHCP server. If you can change line 5:

HTTPServer http;

to

HTTPServer http("wolf",              // Brings up the device with static IP address and domain name.
                IPv4(192,168,0,44),  // IPv4 is a helper function which allows to rtype ipaddresses direct
                IPv4(255,255,255,0), // as numbers in C++.
                IPv4(192,168,0,1),   // the device address is set to 192.168.0.44, netmask 255.255.255.0
                IPv4(192,168,0,1));  // default gateway is 192.168.0.1 and dns to 192.168.0.1 as well.

But change the IP address and netmask and gateway for your network. Have a look here: http://mbed.org/projects/cookbook/api/EMAC/lwip/trunk/HTTPServer/HTTPServer

This should at least bring more information whats wrong.

 

Regards

Rolf

12 Dec 2009

Hi Nick,

Thanks for posting the poinouts you used - after struggling with the cookbook yours did the trick!

Louis

14 Dec 2009

 

Rolf Meyer wrote:

Hi Peter,

Peter Ampt wrote:

 

Hi All,

I'm trying to get the HTTP server example working on my LPC2368 mbed without any success so far. I have a simple index.htm file in the mbed drive. I have tried the pre-compiled code at http://mbed.org/projects/cookbook/svn/EMAC/lwip/examples/HTTPServer_LPC2368.bin and have tried compiling the the source at http://mbed.org/projects/cookbook/svn/EMAC/lwip/examples/HTTPServer with a little pintf at the start of main() for testing.

My set-up has the mbed on a mbed-BOB connected to my Linksys WAG200G wireless router with a crossover Ethernet cable. I get nothing from the USB serial port other than the little message I inserted in the compiled version. The router does not list an IP address for the mbed. Back in August, I successfully tried the nice Ethernet test example at http://mbed.org/projects/cookbook/wiki/EthernetTest with the same crossover Ethernet cable connected to my Windows XP PC with static IP addresses so I am pretty sure the mbed Ethernet works OK. By the way this example no longer compiles-there are heaps of errors; any idea what's changed?

Anyway, I suspect something in the router set-up is not right; I have looked over the router web pages and nothing obvious tells me why it won't DHCP the mbed. I have looked over the Forum at this and related threads and can't find any clues. I would apprecaie any help.

Thanks,

Peter

 

The old EthernetTest example was using another (older) port of lwip. It does not compile anymore with the new library because in version 12 of the mbed library changed the declaration of the pins and some other things. But on the other hand versions >11 allows you to compile for the LPC2368 and LPC1768 without rewriting your code.

The problem you have sounds like a wiring problem but this is just a guess. Can you compile and run ethersniff_hex for me and see if you can see some broadcasting packages from the network. Bets is when you make some broadcasting traffic with your pc (ARP requests or broadcast pings). You should see every arriving package with sender and receiver mac address and a hex dump of the package itself. If it works your connection is fine if not we know its a connection problem.

If it works you describe that you get stuck before you've got a IP address from your DHCP server. If you can change line 5:

HTTPServer http;

to

TTPServer http("wolf",              // Brings up the device with static IP address and domain name.
                IPv4(192,168,0,44),  // IPv4 is a helper function which allows to rtype ipaddresses direct
                IPv4(255,255,255,0), // as numbers in C++.
                IPv4(192,168,0,1),   // the device address is set to 192.168.0.44, netmask 255.255.255.0
                IPv4(192,168,0,1));  // default gateway is 192.168.0.1 and dns to 192.168.0.1 as well.

But change the IP address and netmask and gateway for your network. Have a look here: http://mbed.org/projects/cookbook/api/EMAC/lwip/trunk/HTTPServer/HTTPServer

This should at least bring more information whats wrong.

 

Regards

Rolf

Hi Rolf,

Thanks for explaining what happened with the old EthernetTest example and the changed declarations.

I tried ethersniff_hex; I could see the Ethernet packet traffic with the mbed connected to my PC and router - great! I then tried making the changes to the HTTPServer example by changing the main.cpp "HTTPServer http;" line to that which you suggested. However, the compiler complained that "Identifier "IPv4" was undefined (E20)" and (of course) that the HTTPServer argument list was wrong in file "HTTPServer/main.cpp". I wasn't sure what format the missing IPv4 helper function was supposed to convert the IP addresses to so have had to come back to you for further assistance.

Thanks,

Peter

14 Dec 2009

Hi Peter,

I was working in the last weeks a little bit on the code and might be a little bit confused about which is the live version. The function IPv4 is declared in http://mbed.org/projects/cookbook/svn/EMAC/lwip/trunk/Core/arch/iputil.h and should be automatically included if you include HTTPServer.h.

So it might be help to #include "iputil.h" directly for the moment, but this should not be needed in future.

 

Regards

Rolf

14 Dec 2009

Hi Rolf,

 

Rolf Meyer wrote:

Hi Peter,

I was working in the last weeks a little bit on the code and might be a little bit confused about which is the live version. The function IPv4 is declared in http://mbed.org/projects/cookbook/svn/EMAC/lwip/trunk/Core/arch/iputil.h and should be automatically included if you include HTTPServer.h.

So it might be help to #include "iputil.h" directly for the moment, but this should not be needed in future.

 

Regards

Rolf

Thanks for your advice however adding #include "iputil.h" still caused the compiler to report that "Identifier "IPv4" was undefined (E20)". I couldn't understand why this error occurred so I just I added the necessary bit from iputil.h to main.cpp as follows:

// #include "iputil.h"
// pa20091214 added the following from iputil.h
/*
* This method converts 4 given IPv4 tuples to struct ip_addr classes.
* The Byte are seperated by ,
* Does only work with seperated 4 Byte tuple.
*/
inline struct ip_addr IPv4(u8_t ip0, u8_t ip1, u8_t ip2, u8_t ip3) {
    struct ip_addr addr;
    IP4_ADDR(&addr, ip0, ip1, ip2, ip3);
    return addr;
}
unsigned int base64enc_len(const char *str);
void base64enc(const char *input, unsigned int length, char *output);

// HTTPServer http;  pa20091214 removed and added the following
HTTPServer http("wolf",              // Brings up the device with static IP address and domain name.
                IPv4(192,168,1,44),  // IPv4 is a helper function which allows to rtype ipaddresses direct
                IPv4(255,255,255,0), // as numbers in C++.
                IPv4(192,168,1,1),   // the device address is set to 192.168.0.44, netmask 255.255.255.0
                IPv4(192,168,1,1),   // default gateway is 192.168.0.1 and dns to 192.168.0.1 as well.
                8080);               // And port is on 8080. Default port is 80.

After that the compiler complained that "No instance of constructor "mbed::HTTPServer::HTTPServer" matches the argument list (E289)" in file "HTTPServer/main.cpp". Again I am stuck and needing more advice on how to proceed.

Thanks,

Peter

14 Dec 2009

Hi Peter,

Can you check you lwip library path? It should point to http://mbed.org/projects/cookbook/svn/EMAC/lwip/trunk or http://mbed.org/projects/cookbook/svn/EMAC/lwip/precomp and be at least revision 634.

I've just checked the version alive and it should work without #include "iputil.h"

 

Cheers

Rolf

15 Dec 2009

Hi Rolf,

I imported the lwip library you specified and the HTTPServer example now compiles and works with a static IP address on my network. However I still can't get it to work with DHCP; any ideas on why this may not work?

The following is a HTML question but hope you or someone else can help. I have the following in my index.htm file to turn the mbed LED 1 on and off.

Turn LED 1 <a href="http://192.168.1.144:8080/rpc/led1/write+1">ON</a>
<a href="http://192.168.1.144:8080/rpc/led1/write+0">OFF</a>

This works fine except that when I click on the ON or OFF link, the web browser (of course) goes to a blank page. Is there a way to change the links to send the command without navigating away from the "home" page? Do I have to do this another way?
Thanks,
Peter

15 Dec 2009

Yes, there is another way. I am new to mbed stuff, but I can tell some tricks in HTML.

I had a demo last week to do just what you want. You need Javascript. Here is the code :

<html>
<head>
<title>My RPC command</title>
</head>
<body>
<script>
var staticCall = function(url){
    var myImg = document.createElement("IMG")
        myImg.src = url
}
</script>


<a href="javascript:staticCall('http://192.168.1.144:8080/rpc/led1/write+1')">ON</a>
</body>
</html>

This will ask the server to send an image (which is in fact your RPC command) and will return a black page. This will generate an invisible error in the browser. So this is quick AND dirty ;-)


15 Dec 2009

Hi Stephane,

I saw your great demo. Thanks for sharing your Java script technique, which works great for me too.

Thanks,

Peter

20 Dec 2009

Hi there,

I'm testing the server with static IP address, connected to my home switch. Just for the record, Rolf, i was having the same issue with IPv4 with my version of lwIP library, thanks for the comment.

My (very simple HTML) test page shows only the first time after reset, and then i'm getting the 404 error. Using Firefox on Ubuntu. Pings are OK all the time. With or without favicon, the behavior is the same. Also tried with 10ms delay in main loop.

Am i missing something? I'm not a networking expert, neither probable for me to dig into lwIP for debugging...

 

Regards,

Sebastian.-

03 Mar 2010

Hey guys, i lock up my mbed after sending out about 4000 get commands. I seem to get a timeout than next attempt within the http.get() code.

before get request 
TIMEOUT
       Connection error
                       after get request 
top of main while loop 
before next get request

So basicly i run a loop of 2 get requests. over and over and that's what happened after 2717 itterations. Does this seem to be along the lines of what other people are having for troubles with the http clinet?

ps. that number 2717, can change from anywhere in the 300's to 2500 ish. 2717 is probably a record.

22 Mar 2010

Hi, this is a geat example in RPC with javascript from Stephane ROCHON

Can any one help with a script for read one output and display if it is on or off in the web page?

Tanks

 

 

29 Mar 2010 . Edited: 29 Mar 2010

Hello to everyone!

I am trying to implement the WebServer example but without any success till now (not even the IP address in the serial port). I am using a direct connection between the mbed and my computer (no routers or switches at all). Till now the only example that works perfectly is that one:

 

#include "mbed.h"

Ethernet eth;
Serial pc(USBTX, USBRX); // tx, rx

int main() {
    char buf[0x600];

    while(1) {
        int size = eth.receive();
        if(size > 0) {
            eth.read(buf, size);
            pc.printf("Destination:  %02X:%02X:%02X:%02X:%02X:%02X\r\n",
                    buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
            pc.printf("Source: %02X:%02X:%02X:%02X:%02X:%02X\r\n",
                    buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
        }

        wait(1);
    }
}

I have to use another cable? Any suggestion about my problem?

PS: I am using windows Vista and Mozila Firefox.

 

30 Mar 2010

Hi Ioannis,

Since your mbed is directly connected to your computer, you can't use the mbed's DHCP client unless you have installed a DHCP server your computer, so I assume that your mbed can't get attributed an IP address and gets stuck there.

You can either install a DHCP server on your computer (but is it really worth it...?), or program the mbed to use a local address (like 192.168.x.y for instance).

Example when you instanciate your server :

HTTPServer("mbed", IPv4(192,168,0,101));
For more parameters you can have a look at HTTPServer.h.

Good luck!

30 Mar 2010 . Edited: 30 Mar 2010

Hmmm, interesting evidence!

I am using now the static settings (thanks Donatien) for IP, SubNet, Gateway etc and it seems that works fine only when I connect the mbed with the PC and the operating system (Vista) tries to recognize the network connection.

After a while, the operating systems says that the network connection is unknown (but it still connected) and the mbed stops responding!

26 May 2010

hi all

 

 

I am having trouble with assigning pins to toggle leds on and off.  what im looking to do is this :

1. setup a dynamic http server

2. toggle leds from the webserver

I have been at it for a few days and have made no porgress. can someone please help

27 May 2010

Hi everyone.

I have been developping a new version of the HTTP Server. It is much more stable than the last one, however I would still consider it as being in a beta-testing phasis.

If anyone is interested, I've started to write up some documentation in the beta cookbook.

You can have a look at the two following programs:

NetHttpServerHelloWorld

NetHttpServerExample

Using the latter you should be able to use RPC commands; you can try something like:

http://(mbed IP)/rpc/led4/write 1

to switch led4 on for instance.

27 May 2010

Hi Donatien,

I'm very interested in HTTP Server and other examples you published. I'm looking forward for a more stable implementation. There were and still are issues in the old HTTPServer, however it is kinda working now. What is your approach and what will make yours more stable?

What kind of help do you need? Just give it a try? Or more like real-use scenarios?

For instance, I need a streaming server (preferably using TCP sockets) combined with HTTP Server. This combo will be very useful for sensor applications where one needs a control GUI (webserver) and a streamer for the sensor data (TCP sockets).

I just browsed through your code and noticed some mentioning of the sockets. Do you have or plan an example program? It will probably be less work than documentation.

--

Ilya

28 May 2010

Hi Ilya,

I chose to build up that stack using different layers isolated from each other: the interface-specific layer (which basically contains the Ethernet driver and LwIP), the sockets API, and top-level services (HTTP server/client, NTP client, etc).

The whole stack is polling/events based, and apart from some thread-safe LwIP services, nothing is executed on interrupt. That way, functions in the stack can be non-blocking, and you can run multiple services at the same time (in your case an HTTP Server + a streaming server should not be a problem), plus you avoid loads of "threading" problems.

If you are ready to help, I would love having some feedback regarding bugs, but also ease of use and customization. So if you are ready to implement that stack in your project, I think it would be a great test!

I have not written some example programs for the sockets API yet, however the HTTP server/client and NTP client use that API, so if you want to have a look at the source code I can send it to you.

In the following days I will be writing more documentation, including some on the sockets API.

Donatien