Simple HTTP example

Dependencies:   LWIPInterface NetworkSocketAPI events funcptr mbed-rtos mbed

SimpleHTTP.cpp

Committer:
Christopher Haster
Date:
2016-04-21
Revision:
0:9dd004b6a8b7
Child:
1:ca2041d3a4a6

File content as of revision 0:9dd004b6a8b7:

#include "SimpleHTTP.h"

#define BUFFER_SIZE 4096

SimpleHTTP::SimpleHTTP(EventQueue *queue, NetworkStack *stack)
    : _queue(queue)
    , _stack(stack) {
    memset(&_stats, 0, sizeof _stats);
}

SimpleHTTP::~SimpleHTTP() {
    stop();
}

void SimpleHTTP::start() {
    int err;

    err = _server.open(_stack);
    if (err) _stats.errors++;

    err = _server.bind(80);
    if (err) _stats.errors++;

    err = _server.listen();
    if (err) _stats.errors++;

    _server.set_blocking(false);
    _net_event.attach(_queue, this, &SimpleHTTP::_net_cb);
    _server.attach(&_net_event, &Event<void()>::call);
}

void SimpleHTTP::stop() {
    _server.attach(0);
}

int SimpleHTTP::_handle(char *http) {
    char *buffer = (char *)malloc(BUFFER_SIZE);
    strncpy(buffer, http, BUFFER_SIZE);
    char *type = strtok(http, " ");

    if (strcmp(type, "GET") == 0) {
        char *path = strtok(0, " ");

        if (_get_cbs.count(path) > 0) {
            int size = _get_cbs[path](buffer, BUFFER_SIZE);
            if (size >= 0) {
                size = snprintf(http, BUFFER_SIZE,
                    "HTTP/1.1 200 OK\r\n"
                    "Content-Type: text/html\r\n"
                    "Content-Length: %d\r\n"
                    "\r\n"
                    "%s", size, buffer);
                free(buffer);
                return size;
            }
        }
    }

    free(buffer);
    return snprintf(http, BUFFER_SIZE,
        "HTTP/1.1 404 File Not Found\r\n"
        "\r\n");
}

void SimpleHTTP::_net_cb() {
    int err;
    TCPSocket client;
    err = _server.accept(&client);
    if (err == NSAPI_ERROR_WOULD_BLOCK) {
        return;
    }

    if (err) {
        _stats.errors++;
        return;
    }
    client.set_timeout(2000);
    _stats.accepts++;

    char *buffer = (char *)malloc(BUFFER_SIZE);

    err = client.recv(buffer, BUFFER_SIZE);
    if (err < 0) {
        _stats.errors++;
        free(buffer);
        return;
    }
    _stats.recv += err;

    unsigned size = _handle(buffer);

    err = client.send(buffer, size);
    if (err < 0) {
        _stats.errors++;
        free(buffer);
        return;
    }
    _stats.sent += err;

    err = client.close();
    if (err) _stats.errors++;

    free(buffer);
}

unsigned SimpleHTTP::get_errors() {
    return _stats.errors;
}

unsigned SimpleHTTP::get_accepts() {
    return _stats.accepts;
}

unsigned SimpleHTTP::get_sent() {
    return _stats.sent;
}

unsigned SimpleHTTP::get_recv() {
    return _stats.recv;
}

void SimpleHTTP::get(const char *path, FuncPtr<int(char *, unsigned)> callback) {
    _get_cbs.insert(std::pair<const char *, FuncPtr<int(char *, unsigned)> >(path, callback));
}