Simple HTTP example

Dependencies:   LWIPInterface NetworkSocketAPI events funcptr mbed-rtos mbed

Committer:
Christopher Haster
Date:
Thu Apr 21 18:36:07 2016 -0500
Revision:
0:9dd004b6a8b7
Child:
1:ca2041d3a4a6
Initial commit of simple HTTP server

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