Simple HTTP example

Dependencies:   LWIPInterface NetworkSocketAPI events funcptr mbed-rtos mbed

Committer:
Christopher Haster
Date:
Fri Apr 22 03:21:03 2016 -0500
Revision:
1:ca2041d3a4a6
Parent:
0:9dd004b6a8b7
Match changes to events and take advantage of EventLoop

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Christopher Haster 0:9dd004b6a8b7 1 #include "SimpleHTTP.h"
Christopher Haster 0:9dd004b6a8b7 2
Christopher Haster 0:9dd004b6a8b7 3 #define BUFFER_SIZE 4096
Christopher Haster 0:9dd004b6a8b7 4
Christopher Haster 1:ca2041d3a4a6 5 SimpleHTTP::SimpleHTTP(NetworkStack *stack)
Christopher Haster 1:ca2041d3a4a6 6 : _stack(stack) {
Christopher Haster 0:9dd004b6a8b7 7 memset(&_stats, 0, sizeof _stats);
Christopher Haster 0:9dd004b6a8b7 8 }
Christopher Haster 0:9dd004b6a8b7 9
Christopher Haster 0:9dd004b6a8b7 10 SimpleHTTP::~SimpleHTTP() {
Christopher Haster 0:9dd004b6a8b7 11 stop();
Christopher Haster 0:9dd004b6a8b7 12 }
Christopher Haster 0:9dd004b6a8b7 13
Christopher Haster 0:9dd004b6a8b7 14 void SimpleHTTP::start() {
Christopher Haster 1:ca2041d3a4a6 15 // Startup event loop
Christopher Haster 1:ca2041d3a4a6 16 _loop.start();
Christopher Haster 1:ca2041d3a4a6 17
Christopher Haster 1:ca2041d3a4a6 18 // Startup network code
Christopher Haster 0:9dd004b6a8b7 19 int err;
Christopher Haster 0:9dd004b6a8b7 20
Christopher Haster 0:9dd004b6a8b7 21 err = _server.open(_stack);
Christopher Haster 0:9dd004b6a8b7 22 if (err) _stats.errors++;
Christopher Haster 0:9dd004b6a8b7 23
Christopher Haster 0:9dd004b6a8b7 24 err = _server.bind(80);
Christopher Haster 0:9dd004b6a8b7 25 if (err) _stats.errors++;
Christopher Haster 0:9dd004b6a8b7 26
Christopher Haster 0:9dd004b6a8b7 27 err = _server.listen();
Christopher Haster 0:9dd004b6a8b7 28 if (err) _stats.errors++;
Christopher Haster 0:9dd004b6a8b7 29
Christopher Haster 0:9dd004b6a8b7 30 _server.set_blocking(false);
Christopher Haster 1:ca2041d3a4a6 31 _net_event.attach(&_loop, this, &SimpleHTTP::_net_cb);
Christopher Haster 0:9dd004b6a8b7 32 _server.attach(&_net_event, &Event<void()>::call);
Christopher Haster 0:9dd004b6a8b7 33 }
Christopher Haster 0:9dd004b6a8b7 34
Christopher Haster 0:9dd004b6a8b7 35 void SimpleHTTP::stop() {
Christopher Haster 1:ca2041d3a4a6 36 // Detach server
Christopher Haster 0:9dd004b6a8b7 37 _server.attach(0);
Christopher Haster 1:ca2041d3a4a6 38
Christopher Haster 1:ca2041d3a4a6 39 // End event loop
Christopher Haster 1:ca2041d3a4a6 40 _loop.stop();
Christopher Haster 0:9dd004b6a8b7 41 }
Christopher Haster 0:9dd004b6a8b7 42
Christopher Haster 0:9dd004b6a8b7 43 int SimpleHTTP::_handle(char *http) {
Christopher Haster 0:9dd004b6a8b7 44 char *buffer = (char *)malloc(BUFFER_SIZE);
Christopher Haster 0:9dd004b6a8b7 45 strncpy(buffer, http, BUFFER_SIZE);
Christopher Haster 0:9dd004b6a8b7 46 char *type = strtok(http, " ");
Christopher Haster 0:9dd004b6a8b7 47
Christopher Haster 0:9dd004b6a8b7 48 if (strcmp(type, "GET") == 0) {
Christopher Haster 0:9dd004b6a8b7 49 char *path = strtok(0, " ");
Christopher Haster 0:9dd004b6a8b7 50
Christopher Haster 0:9dd004b6a8b7 51 if (_get_cbs.count(path) > 0) {
Christopher Haster 0:9dd004b6a8b7 52 int size = _get_cbs[path](buffer, BUFFER_SIZE);
Christopher Haster 0:9dd004b6a8b7 53 if (size >= 0) {
Christopher Haster 0:9dd004b6a8b7 54 size = snprintf(http, BUFFER_SIZE,
Christopher Haster 0:9dd004b6a8b7 55 "HTTP/1.1 200 OK\r\n"
Christopher Haster 0:9dd004b6a8b7 56 "Content-Type: text/html\r\n"
Christopher Haster 0:9dd004b6a8b7 57 "Content-Length: %d\r\n"
Christopher Haster 0:9dd004b6a8b7 58 "\r\n"
Christopher Haster 0:9dd004b6a8b7 59 "%s", size, buffer);
Christopher Haster 0:9dd004b6a8b7 60 free(buffer);
Christopher Haster 0:9dd004b6a8b7 61 return size;
Christopher Haster 0:9dd004b6a8b7 62 }
Christopher Haster 0:9dd004b6a8b7 63 }
Christopher Haster 0:9dd004b6a8b7 64 }
Christopher Haster 0:9dd004b6a8b7 65
Christopher Haster 0:9dd004b6a8b7 66 free(buffer);
Christopher Haster 0:9dd004b6a8b7 67 return snprintf(http, BUFFER_SIZE,
Christopher Haster 0:9dd004b6a8b7 68 "HTTP/1.1 404 File Not Found\r\n"
Christopher Haster 0:9dd004b6a8b7 69 "\r\n");
Christopher Haster 0:9dd004b6a8b7 70 }
Christopher Haster 0:9dd004b6a8b7 71
Christopher Haster 0:9dd004b6a8b7 72 void SimpleHTTP::_net_cb() {
Christopher Haster 0:9dd004b6a8b7 73 int err;
Christopher Haster 0:9dd004b6a8b7 74 TCPSocket client;
Christopher Haster 0:9dd004b6a8b7 75 err = _server.accept(&client);
Christopher Haster 0:9dd004b6a8b7 76 if (err == NSAPI_ERROR_WOULD_BLOCK) {
Christopher Haster 0:9dd004b6a8b7 77 return;
Christopher Haster 0:9dd004b6a8b7 78 }
Christopher Haster 0:9dd004b6a8b7 79
Christopher Haster 0:9dd004b6a8b7 80 if (err) {
Christopher Haster 0:9dd004b6a8b7 81 _stats.errors++;
Christopher Haster 0:9dd004b6a8b7 82 return;
Christopher Haster 0:9dd004b6a8b7 83 }
Christopher Haster 0:9dd004b6a8b7 84 client.set_timeout(2000);
Christopher Haster 0:9dd004b6a8b7 85 _stats.accepts++;
Christopher Haster 0:9dd004b6a8b7 86
Christopher Haster 0:9dd004b6a8b7 87 char *buffer = (char *)malloc(BUFFER_SIZE);
Christopher Haster 0:9dd004b6a8b7 88
Christopher Haster 0:9dd004b6a8b7 89 err = client.recv(buffer, BUFFER_SIZE);
Christopher Haster 0:9dd004b6a8b7 90 if (err < 0) {
Christopher Haster 0:9dd004b6a8b7 91 _stats.errors++;
Christopher Haster 0:9dd004b6a8b7 92 free(buffer);
Christopher Haster 0:9dd004b6a8b7 93 return;
Christopher Haster 0:9dd004b6a8b7 94 }
Christopher Haster 0:9dd004b6a8b7 95 _stats.recv += err;
Christopher Haster 0:9dd004b6a8b7 96
Christopher Haster 0:9dd004b6a8b7 97 unsigned size = _handle(buffer);
Christopher Haster 0:9dd004b6a8b7 98
Christopher Haster 0:9dd004b6a8b7 99 err = client.send(buffer, size);
Christopher Haster 0:9dd004b6a8b7 100 if (err < 0) {
Christopher Haster 0:9dd004b6a8b7 101 _stats.errors++;
Christopher Haster 0:9dd004b6a8b7 102 free(buffer);
Christopher Haster 0:9dd004b6a8b7 103 return;
Christopher Haster 0:9dd004b6a8b7 104 }
Christopher Haster 0:9dd004b6a8b7 105 _stats.sent += err;
Christopher Haster 0:9dd004b6a8b7 106
Christopher Haster 0:9dd004b6a8b7 107 err = client.close();
Christopher Haster 0:9dd004b6a8b7 108 if (err) _stats.errors++;
Christopher Haster 0:9dd004b6a8b7 109
Christopher Haster 0:9dd004b6a8b7 110 free(buffer);
Christopher Haster 0:9dd004b6a8b7 111 }
Christopher Haster 0:9dd004b6a8b7 112
Christopher Haster 0:9dd004b6a8b7 113 unsigned SimpleHTTP::get_errors() {
Christopher Haster 0:9dd004b6a8b7 114 return _stats.errors;
Christopher Haster 0:9dd004b6a8b7 115 }
Christopher Haster 0:9dd004b6a8b7 116
Christopher Haster 0:9dd004b6a8b7 117 unsigned SimpleHTTP::get_accepts() {
Christopher Haster 0:9dd004b6a8b7 118 return _stats.accepts;
Christopher Haster 0:9dd004b6a8b7 119 }
Christopher Haster 0:9dd004b6a8b7 120
Christopher Haster 0:9dd004b6a8b7 121 unsigned SimpleHTTP::get_sent() {
Christopher Haster 0:9dd004b6a8b7 122 return _stats.sent;
Christopher Haster 0:9dd004b6a8b7 123 }
Christopher Haster 0:9dd004b6a8b7 124
Christopher Haster 0:9dd004b6a8b7 125 unsigned SimpleHTTP::get_recv() {
Christopher Haster 0:9dd004b6a8b7 126 return _stats.recv;
Christopher Haster 0:9dd004b6a8b7 127 }
Christopher Haster 0:9dd004b6a8b7 128
Christopher Haster 0:9dd004b6a8b7 129 void SimpleHTTP::get(const char *path, FuncPtr<int(char *, unsigned)> callback) {
Christopher Haster 0:9dd004b6a8b7 130 _get_cbs.insert(std::pair<const char *, FuncPtr<int(char *, unsigned)> >(path, callback));
Christopher Haster 0:9dd004b6a8b7 131 }