Webserver example for Nuvoton NuMaker boards and mbed OS 5.15 - HTTP 1.1 and multi-threaded.
For Mbed OS 6, please use the NuMaker-simple-httpd example.
This application demonstrates how to run an HTTP server on an mbed OS 5 device. It is derived from http-webserver-example Request parsing is done through nodejs/http-parser.
Fixed for Mbed OS 5.15 or later
Tested on
NuMaker IoT-M487 with Ethernet NuMaker PFM-M487 with Ethernet
Revision 2:ff1a293c4df3, committed 2020-06-29
- Comitter:
- morgandu
- Date:
- Mon Jun 29 08:17:16 2020 +0000
- Parent:
- 1:fe3df398bdf5
- Commit message:
- Webserver example for mbed OS 5 - HTTP 1.1 and multi-threaded; Fix for mbed OS 5.15 and clean unnecessary libraries; Add fixed IP address option; Test on Nuvoton NuMaker boards.
Changed in this revision
diff -r fe3df398bdf5 -r ff1a293c4df3 README.md --- a/README.md Mon Jul 31 17:12:21 2017 +0200 +++ b/README.md Mon Jun 29 08:17:16 2020 +0000 @@ -1,6 +1,6 @@ # mbed-os-example-http-server -This application demonstrates how to run an HTTP server on an mbed OS 5 device. +This application demonstrates how to run an HTTP server on an mbed OS 5.15 device. Request parsing is done through [nodejs/http-parser](https://github.com/nodejs/http-parser). @@ -16,5 +16,8 @@ * K64F with Ethernet. * NUCLEO_F411RE with ESP8266. * For ESP8266, you need [this patch](https://github.com/ARMmbed/esp8266-driver/pull/41). + +* NuMaker-IoT-M487 with Ethernet +* NuMaker-PFM-M487 with Ethernet But every networking stack that supports the [mbed OS 5 NetworkInterface API](https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/communication/network_sockets/) should work.
diff -r fe3df398bdf5 -r ff1a293c4df3 easy-connect.lib --- a/easy-connect.lib Mon Jul 31 17:12:21 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://github.com/ARMmbed/easy-connect/#e7629734c9846617dd6a55e181a851d7ae7a62b9
diff -r fe3df398bdf5 -r ff1a293c4df3 mbed-http.lib --- a/mbed-http.lib Mon Jul 31 17:12:21 2017 +0200 +++ b/mbed-http.lib Mon Jun 29 08:17:16 2020 +0000 @@ -1,1 +1,1 @@ -https://developer.mbed.org/teams/sandbox/code/mbed-http/#6e0025e01b98 +https://developer.mbed.org/teams/sandbox/code/mbed-http/#a8d157986ad8
diff -r fe3df398bdf5 -r ff1a293c4df3 mbed-os.lib --- a/mbed-os.lib Mon Jul 31 17:12:21 2017 +0200 +++ b/mbed-os.lib Mon Jun 29 08:17:16 2020 +0000 @@ -1,1 +1,1 @@ -https://github.com/ARMmbed/mbed-os/#ed9d1da9dd0c43907ba40cba5ebd9f2c6da3dc07 +https://github.com/ARMmbed/mbed-os/#e4b81f67f939a0c0b11c147ce74aa367271e1279
diff -r fe3df398bdf5 -r ff1a293c4df3 mbed_app.json --- a/mbed_app.json Mon Jul 31 17:12:21 2017 +0200 +++ b/mbed_app.json Mon Jun 29 08:17:16 2020 +0000 @@ -1,50 +1,25 @@ { - "config": { - "network-interface": { - "help": "options are ETHERNET, WIFI_ESP8266, WIFI_ODIN, WIFI_RTW, MESH_LOWPAN_ND, MESH_THREAD", - "value": "ETHERNET" - }, - "mesh_radio_type": { - "help": "options are ATMEL, MCR20, SPIRIT1, EFR32", - "value": "ATMEL" - }, - "esp8266-tx": { - "help": "Pin used as TX (connects to ESP8266 RX)", - "value": "D1" - }, - "esp8266-rx": { - "help": "Pin used as RX (connects to ESP8266 TX)", - "value": "D0" - }, - "esp8266-debug": { - "value": true - }, - "wifi-ssid": { - "value": "\"SSID\"" - }, - "wifi-password": { - "value": "\"Password\"" - } - }, "target_overrides": { "*": { - "target.features_add": ["NANOSTACK", "LOWPAN_ROUTER", "COMMON_PAL"], - "mbed-mesh-api.6lowpan-nd-channel-page": 0, - "mbed-mesh-api.6lowpan-nd-channel": 12, + "platform.default-serial-baud-rate" : 115200, + "platform.stdio-baud-rate" : 115200, + "platform.stdio-convert-newlines" : true, + "platform.stdio-buffered-serial" : false, + "platform.heap-stats-enabled" : 1, + "nsapi.default-wifi-security" : "WPA_WPA2", + "nsapi.default-wifi-ssid" : "\"SSID\"", + "nsapi.default-wifi-password" : "\"PASSWORD\"", "mbed-trace.enable": 0, "mbed-http.http-buffer-size": 2048 }, - "HEXIWEAR": { - "esp8266-tx": "PTD3", - "esp8266-rx": "PTD2" - }, - "NUCLEO_F401RE": { - "esp8266-tx": "D8", - "esp8266-rx": "D2" - }, - "NUCLEO_F411RE": { - "esp8266-tx": "D8", - "esp8266-rx": "D2" + "NUMAKER_IOT_M487": { + "target.network-default-interface-type" : "ETHERNET", + "esp8266.tx" : "PH_8", + "esp8266.rx" : "PH_9", + "esp8266.rts" : "A2", + "esp8266.cts" : "A3", + "esp8266.rst" : "PH_3", + "esp8266.provide-default" : true } } }
diff -r fe3df398bdf5 -r ff1a293c4df3 source/http_server.h --- a/source/http_server.h Mon Jul 31 17:12:21 2017 +0200 +++ b/source/http_server.h Mon Jun 29 08:17:16 2020 +0000 @@ -55,7 +55,7 @@ * Start running the server (it will run on it's own thread) */ nsapi_error_t start(uint16_t port, Callback<void(ParsedHttpRequest* request, TCPSocket* socket)> a_handler) { - server = new TCPServer(); + server = new TCPSocket(); nsapi_error_t ret; @@ -148,10 +148,12 @@ void main() { while (1) { - TCPSocket* clt_sock = new TCPSocket(); // Q: when should these be cleared? When not connected anymore? - SocketAddress clt_addr; - - nsapi_error_t accept_res = server->accept(clt_sock, &clt_addr); + TCPSocket* clt_sock; // = new TCPSocket(); // Q: when should these be cleared? When not connected anymore? + //SocketAddress clt_addr; + nsapi_error_t accept_res; + + //nsapi_error_t accept_res = server->accept(clt_sock, &clt_addr); + clt_sock = server->accept(&accept_res); if (accept_res == NSAPI_ERROR_OK) { sockets.push_back(clt_sock); // so we can clear our disconnected sockets @@ -165,14 +167,15 @@ socket_threads.push_back(m); } else { - delete clt_sock; + //delete clt_sock; } for (size_t ix = 0; ix < socket_threads.size(); ix++) { if (socket_threads[ix]->thread->get_state() == Thread::Deleted) { socket_threads[ix]->thread->terminate(); delete socket_threads[ix]->thread; - delete socket_threads[ix]->socket; // does this work on esp8266? + //delete socket_threads[ix]->socket; // does this work on esp8266? + socket_threads[ix]->socket->close(); socket_threads.erase(socket_threads.begin() + ix); // what if there are two? } } @@ -185,7 +188,7 @@ Thread* thread; } socket_thread_metadata_t; - TCPServer* server; + TCPSocket* server; NetworkInterface* _network; Thread main_thread; vector<TCPSocket*> sockets;
diff -r fe3df398bdf5 -r ff1a293c4df3 source/main.cpp --- a/source/main.cpp Mon Jul 31 17:12:21 2017 +0200 +++ b/source/main.cpp Mon Jun 29 08:17:16 2020 +0000 @@ -1,9 +1,9 @@ #include "mbed.h" -#include "easy-connect.h" #include "http_server.h" #include "http_response_builder.h" -Serial pc(USBTX, USBRX); +#define USE_FIXED_IP 1 // 1 for fixed IP, 0 for DHCP + DigitalOut led(LED1); // Requests come in here @@ -40,24 +40,35 @@ } int main() { - pc.baud(115200); // Connect to the network (see mbed_app.json for the connectivity method used) - NetworkInterface* network = easy_connect(true); + NetworkInterface *network = NetworkInterface::get_default_instance(); if (!network) { printf("Cannot connect to the network, see serial output\n"); return 1; } +#if USE_FIXED_IP + // This fixed IP address is convenient to test with Windows PC + SocketAddress ip_addr("169.254.108.2"); + SocketAddress ip_mask("255.255.0.0"); + SocketAddress ip_gwaddr("169.254.108.1"); + network->set_network(ip_addr, ip_mask, ip_gwaddr); +#endif + + network->connect(); + HttpServer server(network); - nsapi_error_t res = server.start(8080, &request_handler); + nsapi_error_t res = server.start(80, &request_handler); if (res == NSAPI_ERROR_OK) { - printf("Server is listening at http://%s:8080\n", network->get_ip_address()); + SocketAddress ip_addr; + network->get_ip_address(&ip_addr); + printf("Server is listening at http://%s\n", ip_addr.get_ip_address()); } else { printf("Server could not be started... %d\n", res); } - wait(osWaitForever); + while(1) ThisThread::sleep_for(1000000); }