Simple HTTP example

Dependencies:   LWIPInterface NetworkSocketAPI events funcptr mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleHTTP.cpp Source File

SimpleHTTP.cpp

00001 #include "SimpleHTTP.h"
00002 
00003 #define BUFFER_SIZE 4096
00004 
00005 SimpleHTTP::SimpleHTTP(NetworkStack *stack)
00006     : _stack(stack) {
00007     memset(&_stats, 0, sizeof _stats);
00008 }
00009 
00010 SimpleHTTP::~SimpleHTTP() {
00011     stop();
00012 }
00013 
00014 void SimpleHTTP::start() {
00015     // Startup event loop
00016     _loop.start();
00017 
00018     // Startup network code
00019     int err;
00020 
00021     err = _server.open(_stack);
00022     if (err) _stats.errors++;
00023 
00024     err = _server.bind(80);
00025     if (err) _stats.errors++;
00026 
00027     err = _server.listen();
00028     if (err) _stats.errors++;
00029 
00030     _server.set_blocking(false);
00031     _net_event.attach(&_loop, this, &SimpleHTTP::_net_cb);
00032     _server.attach(&_net_event, &Event<void()>::call);
00033 }
00034 
00035 void SimpleHTTP::stop() {
00036     // Detach server
00037     _server.attach(0);
00038 
00039     // End event loop
00040     _loop.stop();
00041 }
00042 
00043 int SimpleHTTP::_handle(char *http) {
00044     char *buffer = (char *)malloc(BUFFER_SIZE);
00045     strncpy(buffer, http, BUFFER_SIZE);
00046     char *type = strtok(http, " ");
00047 
00048     if (strcmp(type, "GET") == 0) {
00049         char *path = strtok(0, " ");
00050 
00051         if (_get_cbs.count(path) > 0) {
00052             int size = _get_cbs[path](buffer, BUFFER_SIZE);
00053             if (size >= 0) {
00054                 size = snprintf(http, BUFFER_SIZE,
00055                     "HTTP/1.1 200 OK\r\n"
00056                     "Content-Type: text/html\r\n"
00057                     "Content-Length: %d\r\n"
00058                     "\r\n"
00059                     "%s", size, buffer);
00060                 free(buffer);
00061                 return size;
00062             }
00063         }
00064     }
00065 
00066     free(buffer);
00067     return snprintf(http, BUFFER_SIZE,
00068         "HTTP/1.1 404 File Not Found\r\n"
00069         "\r\n");
00070 }
00071 
00072 void SimpleHTTP::_net_cb() {
00073     int err;
00074     TCPSocket client;
00075     err = _server.accept(&client);
00076     if (err == NSAPI_ERROR_WOULD_BLOCK) {
00077         return;
00078     }
00079 
00080     if (err) {
00081         _stats.errors++;
00082         return;
00083     }
00084     client.set_timeout(2000);
00085     _stats.accepts++;
00086 
00087     char *buffer = (char *)malloc(BUFFER_SIZE);
00088 
00089     err = client.recv(buffer, BUFFER_SIZE);
00090     if (err < 0) {
00091         _stats.errors++;
00092         free(buffer);
00093         return;
00094     }
00095     _stats.recv += err;
00096 
00097     unsigned size = _handle(buffer);
00098 
00099     err = client.send(buffer, size);
00100     if (err < 0) {
00101         _stats.errors++;
00102         free(buffer);
00103         return;
00104     }
00105     _stats.sent += err;
00106 
00107     err = client.close();
00108     if (err) _stats.errors++;
00109 
00110     free(buffer);
00111 }
00112 
00113 unsigned SimpleHTTP::get_errors() {
00114     return _stats.errors;
00115 }
00116 
00117 unsigned SimpleHTTP::get_accepts() {
00118     return _stats.accepts;
00119 }
00120 
00121 unsigned SimpleHTTP::get_sent() {
00122     return _stats.sent;
00123 }
00124 
00125 unsigned SimpleHTTP::get_recv() {
00126     return _stats.recv;
00127 }
00128 
00129 void SimpleHTTP::get(const char *path, FuncPtr<int(char *, unsigned)> callback) {
00130     _get_cbs.insert(std::pair<const char *, FuncPtr<int(char *, unsigned)> >(path, callback));
00131 }