Simple HTTP example
Dependencies: LWIPInterface NetworkSocketAPI events funcptr mbed-rtos mbed
SimpleHTTP.cpp@1:ca2041d3a4a6, 2016-04-22 (annotated)
- 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?
User | Revision | Line number | New 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 | } |