tags:

views:

351

answers:

4

I'm starting up a new embedded system design using FreeRTOS. My last one used eCos, which has a built-in HTTP server that's really lightweight, especially since I didn't have a filesystem. The way it worked, in short, was that every page was a CGI-like C function that got called when needed by the HTTP daemon. Specifically, you would write a function of the form:

int MyWebPage(FILE* resp, const char* page, const char* params, void* uData);

where page was the page part of the url, params were any form parameters (only GET was supported, not POST, which prevented file uploads and thus made burning the flash a pain), uData is a token passed in that was set when you registered the function, so you could have the same function serve multiple URLs or ranges with different data, and resp is a file handle that you write the HTTP response (headers and all) out to.

Then you registered the function with:

CYG_HTTPD_TABLE_ENTRY(www_myPage, "/", MyWebPage, 0);

where CYG_HTTPD_TABLE_ENTRY is a macro where the first parameter was a variable name, the second was a page URL (the * wildcard is allowed; hence page getting passed to MyWebPage()), third is the function pointer, and last is the uData value.

So a simple example:

int HelloWorldPage(FILE* resp, const char*, const char* params, void*)
{
    fprintf("Content-Type: text/html;\n\n");
    fprintf("<html><head><title>Hello World!</title></head>\n");
    fprintf("<body>\n");
    fprintf("<h1>Hello, World!</h1>\n");
    fprintf("<p>You passed in: %s</p>\n", params);
    fprintf("</body></html>\n");
}
CYG_HTTPD_TABLE_ENTRY(www_hello, "/", HelloWorldPage, 0);

(Actually, params would be passed through a function to escape the HTML magic characters, and I'd use another couple functions to split the params and make a <ul> out of it, but I left that out for clarity.)

The server itself just ran as a task (i.e. thread) and didn't get in the way as long as it had a lower priority than the critical tasks.

Needless to say, having this proved invaluable for testing and debugging. (One problem with embedded work is that you generally can't toss up an XTerm to use as a log.) So when Supreme Programmer reflexively blamed me for something not working (path of least resistance, I guess), I could pull up the web page and show that he had sent me bad parameters. Saved a lot of debug time in integration.

So anyway... I'm wondering, is there something like this available as an independent library? Something that I can link in, register my callbacks, spawn a thread, and let it do the magic? Or do I need to crank out my own? I'd prefer C++, but can probably use a C library as well.

EDIT: Since I'm putting a bounty on it, I need to clarify that the library would need to be under an open-source license.

A: 

I'm not familiar with FreeRTOS and how it supports TCP/IP and sockets, so I can't say for sure but you might want to take a look at the GoAhead web server. http://www.goahead.com/products/webserver/ossupport.aspx

Richard Pennington
FreeRTOS doesn't provide its own IP stack, but it does support LwIP and uIP. Basically, I'll be fine with a library that supports a sockets-like API or if a library needs me to write some "send these bytes" and "received those bytes" functions.
Mike DeSimone
A: 

http://www.ibm.com/developerworks/systems/library/es-nweb/index.html

Seems exactly what you are after. You my need to do a small amount of re-writing to get it to run under FreeRTOS but its a very small, very lightweight web server.

Goz
From that page: "static pages only". I'm looking for dynamic page support (GET and POST, the latter required for sane flash upload support). Anyway, it's better than starting from scratch.
Mike DeSimone
+1  A: 

Mongoose is licensed under MIT License and is lightweight (just one C file so easy to include into a new project). It will run in a separate thread and support callbacks.

Zitrax
Looks really close. I need to look through the source and see if it will choke on `<form method="POST" enctype="multipart/form-data">`. Other downside is that it launches the thread for you (assumes POSIX.4a, I guess?), but that shouldn't be a huge deal to work around.
Mike DeSimone
+2  A: 

I suggest you have a look at libmicrohttpd, the embedded web server:

It is small and fast, has a simple C API, supports multithreading, is suitable for embedded systems, supports POST, optionally supports SSL/TLS, and is available under either the LGPL or eCos license (depending). I believe this fulfils all your requirements. It would be trivial to wrapper in C++ if you preferred.

gavinb