HTTP Server

28 May 2010

Hi Donatien,

>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!

Yes, I am ready. From what you say the architecture in your implementation fits perfectly the application I have. It seems like I will need the source code for getting started with sockets. Besides, to me source code is almost always better than documentation, so I can start before any documentation is available.

--

Ilya

10 Jun 2010

Time flies! I was able to compile from source and run just the HTTP server part, did not try the sockets yet. Here are some random observations:

  1. I used the main file from NetHttpServerExample.
  2. Compile was failing, needed to pick the right file from two NetCfg.h variants - the one in EthApi worked.
  3. Looks like DHCP times out quicker and throws an MBED error if cable is not plugged in. Better than old HTTPServer/Client hanging for few minutes, but worse that can't proceed. Still don't see the timeout setting, and it would be better to have soft error instead of error lights. Some applications need to keep going without network and try DHCP upon plugin - callback mechanism needed.
  4. Can't get to serve http://a.b.c.d/index.htm - always need ../webfs/index.htm. For one, that makes it impossible to serve favicon.ico that browsers quietly ask for. Tried both svr.addHandler<FSHandler>("") and svr.addHandler<FSHandler>("/"). On plus side can see how to modify FSHandler.cpp to work that out.
  5. Can't autoresolve http://a.b.c.d/ to serve index.htm. Also can rework the source.
  6. Can't see "File not found.' in Google Chrome, but see it in Firefox. Google chrome gives "Oops! This link appears to be broken." Something is probably missing in the 404 error page.
  7. Very slow serving of image files - got a measly 1200B/s!! Also noticed that it spits chunks of data at the rate of LED blinking. Could not see how it can be happening in the main() code using while loop and the timer. Can it be that the tm.restart() taking too much time? Will check that.
I will proceed to the sockets and post more as it comes along.
10 Jun 2010 . Edited: 10 Jun 2010

I've been playing with the socket API a bit as it seems to be just what I need, but I've run into a brick wall.  Can anyone point me in the right direction?  So far, I have:

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TcpSocket.h"
#include "UdpSocket.h"

EthernetNetIf eth;
TcpSocket tcpSock;
UdpSocket udpSock;

int main() {
    printf("Start\n");

    printf("\r\nSetting up...\r\n");
    EthernetErr ethErr = eth.setup();
    if(ethErr) {
        printf("Error %d in setup.\n", ethErr);
        return -1;
    }
    IpAddr ip = eth.getIp();
    printf("IP Address: %d.%d.%d.%d\r\n", ip[0], ip[1], ip[2], ip[3]); // Turns out the library does this anyway
    
    TcpSocketErr sockErr = tcpSock.bind(Host(IP_ADDR_ANY, 7)); // Trying to make a simple echo server on port 7
    if(sockErr) {
        printf("Error %d in binding TCP socket\r\n", sockErr);
        return -1;
    }
    
    sockErr = tcpSock.listen();
    if(sockErr) {
        printf("Error %d in listening to TCP socket\r\n", sockErr);
        return -1;
    }
    
    printf("Entering while loop just Net::poll()ing\r\n");
    while(1) {
        Net::poll();
    }
}

But now what, what do I do with the socket? I hooked up a method to be called on events using:

void onNetTcpSocketEvent(TcpSocketEvent e) {
    switch (e) {
        case TCPSOCKET_CONNECTED:
            printf("TCPSOCKET_CONNECTED\r\n");
            break;
        case TCPSOCKET_ACCEPT:
            printf("TCPSOCKET_ACCEPT\r\n");
            break;
        default:
            printf("Socket event %d\r\n", e);
    }
}

int main() {
    // ...
    void (*pt2Function)(TcpSocketEvent) = NULL;
    pt2Function = &onNetTcpSocketEvent;
    tcpSock.setOnEvent(pt2Function);
    (*pt2Function) (TCPSOCKET_CONNECTED);
    // ....
} 

This calls the onNetTcpSocketEvent function on TCPSOCKET_ACCEPT, but I'm at a loss as to what I do next. I'm guessing something like:

            Host *h;
            TcpSocket **s;
            TcpSocketErr tcpSockErr = tcpSock.accept(h, s);
            if(tcpSockErr) {
                printf("Error %d in accepting socket\r\n", tcpSockErr);
                break;
            }
            IpAddr clientIp = h->getIp();
            printf("Client: %d.%d.%d.%d", clientIp[0], clientIp[1], clientIp[2], clientIp[3]);

But this seems to die a horrible death when I try to call h->getIp(); If I can get this sorted, what I'd like to do is get this working as a basic echo server on TCP and UDP and then document it as some sort of guide to using this excellent socket API.  In the meantime I've got my head buried in a C++ book as coming from the sheltered life of Java and C#, pointers are quite scary and as is quite possibly obvious from my last code snippet, I need to do a fair bit of learning.

11 Jun 2010

Hi everyone,

First of all thank you for this feedback, I will take the time to look at these issues. Regarding the sockets API, I know that this seriously lacks documentation; I have to update the cookbook next week anyway, so the sockets API will probably be part of the new pages.

Meanwhile, I have released the source for the stack here, which can be useful if you want to get started furing the weekend: http://mbed.org/users/donatien/programs/NetServicesSource

Feel also free to have a look at this dedicated forum thread and this new wiki page.