Webserver example for Nuvoton NuMaker boards and mbed OS 5.15 - HTTP 1.1 and multi-threaded.

Dependencies:   mbed-http

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

Files at this revision

API Documentation at this revision

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

README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect.lib Show diff for this revision Revisions of this file
mbed-http.lib Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
source/http_server.h Show annotated file Show diff for this revision Revisions of this file
source/main.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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.
--- 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
--- 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
--- 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
--- 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
         }
     }
 }
--- 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;
--- 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);
 }