A simple web server mainly based on ideas from Jasper Schuurmans Netduino web server

Dependents:   RdBlindsServer SpideyWallWeb RdGasUseMonitor

A fast and reliable web server for MBED! http://robdobson.com/2015/08/a-reliable-mbed-webserver/

It has a very neat way to implement REST commands and can serve files from local storage (on LPC1768 for instance) and from SD cards. It also has a caching facility which is particularly useful for serving files from local storage.

The server can be run in the main() thread (and has a sub-2ms response time if this is done) or in a mbed-rtos thread which increases the response time to (a still respectable) 30ms or so.

The latest project that uses this is here - https://developer.mbed.org/users/Bobty/code/SpideyWallWeb/

int main (void)
{
    // Ethernet interface
    EthernetInterface::init();

    // Connect ethernet
    EthernetInterface::connect();

    // Init the web server
    pc.printf("Starting web server\r\n");
    char* baseWebFolder = "/sd/";  // should be /sd/ for SDcard files - not used for local file system
    RdWebServer webServer;
    
    // Add commands to handle the home page and favicon
    webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, "index.htm", true);
    webServer.addCommand("favicon.ico", RdWebServerCmdDef::CMD_LOCALFILE, NULL, NULL, true);
    
    // Add the lightwall control commands
    webServer.addCommand("name", RdWebServerCmdDef::CMD_CALLBACK, &lightwallGetSystemName);
    webServer.addCommand("clear", RdWebServerCmdDef::CMD_CALLBACK, &lightwallClear);
    webServer.addCommand("rawfill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallRawFill);
    webServer.addCommand("fill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallFill);
    webServer.addCommand("showleds", RdWebServerCmdDef::CMD_CALLBACK, &lightwallShowLeds);
    
    // Start the server
    webServer.init(WEBPORT, &led4, baseWebFolder);
    webServer.run();

}

// Get system name - No arguments required
char* lightwallGetSystemName(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
                int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
{
    // Perform any required actions here ....

    // ...

    // Return the system name
    return systemName;
}

This server was originally based on a Netduino web server from Jasper Schuurmans but has been optimised for speed.

Files at this revision

API Documentation at this revision

Comitter:
Bobty
Date:
Tue May 05 20:27:33 2015 +0000
Parent:
14:4b83670854f0
Child:
16:0248bbfdb6c1
Commit message:
Pared back for work on stability - ok on LPC1768

Changed in this revision

RdWebServer.cpp Show annotated file Show diff for this revision Revisions of this file
RdWebServer.h Show annotated file Show diff for this revision Revisions of this file
--- a/RdWebServer.cpp	Tue May 05 15:05:44 2015 +0000
+++ b/RdWebServer.cpp	Tue May 05 20:27:33 2015 +0000
@@ -1,5 +1,5 @@
 /* RdWebServer.cpp
-   Rob Dobson 2013
+   Rob Dobson 2013-2015
    Inspired by Jasper Schuurmans multi-threaded web server for Netduino http://www.schuurmans.cc/multi-threaded-web-server-for-netduino-plus
    More details at http://robdobson.com/2013/10/moving-my-window-shades-control-to-mbed/
 */
@@ -8,14 +8,14 @@
 
 #include "RdWebServer.h"
 
-#define MAX_CMDSTR_LEN 100
-#define MAX_ARGSTR_LEN 100
-#define MAX_FILENAME_LEN (MAX_ARGSTR_LEN + 20)
-#define MAX_MIMETYPE_LEN 50
+const int MAX_CMDSTR_LEN = 100;
+const int MAX_ARGSTR_LEN = 100;
+const int MAX_FILENAME_LEN = (MAX_ARGSTR_LEN + 20);
+const int MAX_MIMETYPE_LEN = 50;
 
 RdWebServer::RdWebServer()
 {
-    _serverIsListening = false;
+    _initOk = false;
     _pStatusLed = NULL;
 }
 
@@ -28,38 +28,164 @@
 
 bool RdWebServer::init(int port, DigitalOut* pStatusLed, char* pBaseWebFolder)
 {
+    // Settings
     _port = port;
     _pStatusLed = pStatusLed;
     _pBaseWebFolder = pBaseWebFolder;
-        
-    _socketSrv.set_blocking(true);
 
-    //setup tcp socket
-    if(_socketSrv.bind(port)< 0) 
+    // Setup tcp socket
+    _serverSocket.set_blocking(true);
+    if(_serverSocket.bind(port)< 0) 
     {
         RD_WARN("TCP server bind fail\n\r");
         return false;
     }
-    else 
-    {
-        RD_DBG("TCP server bind success\n\r");
-        _serverIsListening = true;
-    }
-
-    if(_socketSrv.listen(1) < 0)
+    if(_serverSocket.listen(1) < 0)
     {
         RD_WARN("TCP server listen fail\n\r");
         return false;
     }
-    else 
-    {
-        RD_INFO("TCP server is listening...\r\n");
-    }
-    
+    RD_INFO("TCP server is listening...\r\n");
+    _initOk = true;
     return true;
 }
 
-bool RdWebServer::handleReceivedHttp(TCPSocketConnection &client)
+void RdWebServer::run()
+{
+    // Check initialised ok
+    if (!_initOk)
+        return;
+    
+    bool blockingOnAccept = true;
+    bool blockingOnReceive = true;
+    int timeoutOnBlocking = 2000;
+    const char* closeConnStr = "Connection: Close\r\n";
+    bool closeConnAfterSend = false;
+    bool closeConnOnReceiveFail = true;
+    
+    // Start accepting connections
+    while (true)
+    {
+        TCPSocketConnection clientSocketConn;
+        // Accept connection if available
+        RD_INFO("Waiting for TCP connection\r\n");
+        clientSocketConn.set_blocking(blockingOnAccept, timeoutOnBlocking);
+        if(_serverSocket.accept(clientSocketConn)<0) 
+        {
+            RD_WARN("TCP Socket failed to accept connection\n\r");
+            continue;
+        }
+        
+        // Connection
+        RD_INFO("Connection from IP: %s\n\r", clientSocketConn.get_address());
+        if (_pStatusLed != NULL)
+            *_pStatusLed = true;
+        
+        // While connected
+        bool forcedClosed = false;
+        while(clientSocketConn.is_connected() && !forcedClosed)
+        {
+            // Receive data
+            clientSocketConn.set_blocking(blockingOnReceive, timeoutOnBlocking);
+            int rxLen = clientSocketConn.receive(_buffer, HTTPD_MAX_REQ_LENGTH);
+            if (rxLen == -1)
+            {
+                RD_DBG("clientSocketConn.receive() returned %d\r\n", rxLen);
+                if (closeConnOnReceiveFail)
+                {
+                    int closeRet = clientSocketConn.close();
+                    RD_DBG("Failed receive connection close() ret %d is connected %d\r\n", closeRet, clientSocketConn.is_connected());
+                    forcedClosed = true;
+                }
+                continue;
+            }
+            if (rxLen == 0)
+            {
+                RD_DBG("clientSocketConn.receive() returned %d - ignoring\r\n", rxLen);
+                continue;
+            }
+            if (rxLen > HTTPD_MAX_REQ_LENGTH)
+            {
+                RD_DBG("clientSocketConn.receive() returned %d - too long\r\n", rxLen);
+                continue;
+            }
+        
+            RD_DBG("Received len %d\r\n", rxLen);
+            _buffer[rxLen] = '\0';
+            RD_DBG("%s\r\n", _buffer);
+            
+            // Send a response
+            char* content = "HELLO\r\n";
+            int sz = strlen(content);
+            sprintf(_httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n%s\r\n", sz, closeConnAfterSend ? closeConnStr : "");
+            int sentRet = clientSocketConn.send(_httpHeader,strlen(_httpHeader));
+            int sentRet2 = clientSocketConn.send(content, strlen(content));
+            
+            RD_DBG("Sent %s header ret %d content ret %d now connected %d\r\n", content, sentRet, sentRet2, clientSocketConn.is_connected());
+            
+            if (closeConnAfterSend)
+            {
+                int closeRet = clientSocketConn.close();
+                RD_DBG("After send connection close() ret %d\r\n", closeRet);
+            }
+        }
+    }
+}
+            
+//            connectLimitTimer.reset();
+//            connectLimitTimer.start();
+//            while(true)
+//            {
+//                // Check connection timer - 10 seconds timeout on HTTP operation
+//                if (connectLimitTimer.read() >= 10)
+//                {
+//                    RD_WARN("Connection timed out\n\r");
+//                    break;
+//                }
+//                // Get received data
+//                int rxLen = clientSocketConn.receive(_buffer, HTTPD_MAX_REQ_LENGTH);
+//                if (rxLen == -1)
+//                {
+//                    RD_WARN("Nothing received\n\r");
+//                    continue;
+//                }
+//                else if (rxLen == 0)
+//                {
+//                    RD_WARN("received buffer is empty.\n\r");
+//                    break;                
+//                }
+//                else if (rxLen > HTTPD_MAX_REQ_LENGTH)
+//                {
+//                    sprintf(_httpHeader,"HTTP/1.1 413 Request Entity Too Large \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
+//                    clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
+//                    clientSocketConn.send_all(_buffer, rxLen);
+//                    break;
+//                }
+//                _buffer[rxLen] = '\0';
+//    
+//                // Handle buffer
+//                if (handleReceivedHttp(clientSocketConn))
+//                {
+//                    break;
+//                }
+//                else
+//                {
+//                    connectLimitTimer.reset();
+//                    connectLimitTimer.start();
+//                }
+//            }
+//            
+//            // Connection now closed
+//            RD_INFO("Connection closed ...\r\n");
+//            clientSocketConn.close();
+//            if (_pStatusLed != NULL)
+//                *_pStatusLed = false;
+//        }
+//        
+//    }
+//}
+//
+bool RdWebServer::handleReceivedHttp(TCPSocketConnection &clientSocketConn)
 {
     bool closeConn = true;
     RD_DBG("Received Data: %d\n\r\n\r%.*s\n\r",strlen(_buffer),strlen(_buffer),_buffer);
@@ -86,36 +212,40 @@
                 if ((*it)->_cmdType == RdWebServerCmdDef::CMD_CALLBACK)
                 {
                     char* respStr = ((*it)->_callback)(method, cmdStr, argStr);
-                    client.send_all(respStr, strlen(respStr));
+                    clientSocketConn.send_all(respStr, strlen(respStr));
                 }
                 else if ((*it)->_cmdType == RdWebServerCmdDef::CMD_LOCALFILE)
                 {
+#ifdef SUPPORT_LOCAL_FILE_CACHE
                     if ((*it)->_substFileName[0] != '\0')
                     {
                         char combinedFileName[MAX_FILENAME_LEN];
                         strcpy(combinedFileName, (*it)->_substFileName);
                         if (combinedFileName[strlen(combinedFileName)-1] == '*')
                             strcpy(combinedFileName+strlen(combinedFileName)-1, argStr);
-                        handleLocalFileRequest(combinedFileName, argStr, client, _httpHeader, (*it)->_bCacheIfPossible);
+                        handleLocalFileRequest(combinedFileName, argStr, clientSocketConn, _httpHeader, (*it)->_bCacheIfPossible);
                     }
                     else
+#endif
                     {
-                        handleLocalFileRequest(cmdStr, argStr, client, _httpHeader, (*it)->_bCacheIfPossible);
+                        handleLocalFileRequest(cmdStr, argStr, clientSocketConn, _httpHeader, (*it)->_bCacheIfPossible);
                     }
                 }
                 else if ((*it)->_cmdType == RdWebServerCmdDef::CMD_SDORUSBFILE)
                 {
+#ifdef SUPPORT_LOCAL_FILE_CACHE
                     if ((*it)->_substFileName[0] != '\0')
                     {
                         char combinedFileName[MAX_FILENAME_LEN];
                         strcpy(combinedFileName, (*it)->_substFileName);
                         if (combinedFileName[strlen(combinedFileName)-1] == '*')
                             strcpy(combinedFileName+strlen(combinedFileName)-1, argStr);
-                        closeConn = handleSDFileRequest(combinedFileName, argStr, client, _httpHeader);
+                        closeConn = handleSDFileRequest(combinedFileName, argStr, clientSocketConn, _httpHeader);
                     }
                     else
+#endif
                     {
-                        closeConn = handleSDFileRequest(cmdStr, argStr, client, _httpHeader);
+                        closeConn = handleSDFileRequest(cmdStr, argStr, clientSocketConn, _httpHeader);
                     }
                 }
                 break;
@@ -123,89 +253,17 @@
         }
         // If command not found see if it is a local file
         if (!cmdFound)
-            closeConn = handleSDFileRequest(cmdStr, argStr, client, _httpHeader);
+            closeConn = handleSDFileRequest(cmdStr, argStr, clientSocketConn, _httpHeader);
     }
     return closeConn;
 }
 
-void RdWebServer::run()
-{
-    TCPSocketConnection client;
-    Timer connectLimitTimer;
-
-    while (isListening())
-    {
-        RD_INFO("Waiting for TCP connection\r\n");
-        if(_socketSrv.accept(client)<0) 
-        {
-            RD_WARN("TCP Socket failed to accept connection\n\r");
-        }
-        else
-        {
-            client.set_blocking(false, 2000);
-            RD_INFO("Connection from IP: %s\n\r",client.get_address());
-            if (_pStatusLed != NULL)
-                *_pStatusLed = true;
-            
-            connectLimitTimer.reset();
-            connectLimitTimer.start();
-            while(true)
-            {
-                // Check connection timer - 10 seconds timeout on HTTP operation
-                if (connectLimitTimer.read() >= 10)
-                {
-                    RD_WARN("Connection timed out\n\r");
-                    break;
-                }
-                // Get received data
-                int rxLen = client.receive(_buffer, HTTPD_MAX_REQ_LENGTH);
-                if (rxLen == -1)
-                {
-                    RD_WARN("Nothing received\n\r");
-                    continue;
-                }
-                else if (rxLen == 0)
-                {
-                    RD_WARN("received buffer is empty.\n\r");
-                    break;                
-                }
-                else if (rxLen > HTTPD_MAX_REQ_LENGTH)
-                {
-                    sprintf(_httpHeader,"HTTP/1.1 413 Request Entity Too Large \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
-                    client.send_all(_httpHeader,strlen(_httpHeader));
-                    client.send_all(_buffer, rxLen);
-                    break;
-                }
-                _buffer[rxLen] = '\0';
-    
-                // Handle buffer
-                if (handleReceivedHttp(client))
-                {
-                    break;
-                }
-                else
-                {
-                    connectLimitTimer.reset();
-                    connectLimitTimer.start();
-                }
-            }
-            
-            // Connection now closed
-            RD_INFO("Connection closed ...\r\n");
-            client.close();
-            if (_pStatusLed != NULL)
-                *_pStatusLed = false;
-        }
-        
-    }
-}
-
 void RdWebServer::addCommand(char* pCmdStr, int cmdType, CmdCallbackType callback, char* substFileName, bool cacheIfPossible)
 {
     _commands.push_back(new RdWebServerCmdDef(pCmdStr, cmdType, callback, substFileName, cacheIfPossible));
 }
 
-bool RdWebServer::handleSDFileRequest(char* inFileName, char* argStr, TCPSocketConnection &client, char* httpHeader)
+bool RdWebServer::handleSDFileRequest(char* inFileName, char* argStr, TCPSocketConnection &clientSocketConn, char* httpHeader)
 {
     bool closeConn = true;
     const int HTTPD_MAX_FNAME_LENGTH = 127;
@@ -222,21 +280,21 @@
         if (d != NULL) 
         {
             sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
-            client.send_all(httpHeader,strlen(httpHeader));
+            clientSocketConn.send_all(httpHeader,strlen(httpHeader));
             sprintf(httpHeader,"<html><head><title>Directory Listing</title></head><body><h1>%s</h1><ul>", inFileName);
-            client.send_all(httpHeader,strlen(httpHeader));
+            clientSocketConn.send_all(httpHeader,strlen(httpHeader));
             struct dirent *p;
             while((p = readdir(d)) != NULL) 
             {
                 RD_INFO("%s\r\n", p->d_name);
                 sprintf(httpHeader,"<li>%s</li>", p->d_name);
-                client.send_all(httpHeader,strlen(httpHeader));
+                clientSocketConn.send_all(httpHeader,strlen(httpHeader));
             }
         }
         closedir(d);
         RD_DBG("Directory closed\n");
         sprintf(httpHeader,"</ul></body></html>");
-        client.send_all(httpHeader,strlen(httpHeader));
+        clientSocketConn.send_all(httpHeader,strlen(httpHeader));
     }
     else
 #endif
@@ -249,7 +307,7 @@
         {
             RD_WARN("Filename %s not found\r\n", filename);
             sprintf(httpHeader,"HTTP/1.1 404 Not Found \r\nContent-Type: text\r\nContent-Length: 0\r\n\r\n");
-            client.send_all(httpHeader,strlen(httpHeader));
+            clientSocketConn.send_all(httpHeader,strlen(httpHeader));
             closeConn = false;
         }
         else
@@ -259,7 +317,7 @@
             int sz = ftell(fp);
             fseek(fp, 0L, SEEK_SET);
             sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n", sz);
-            client.send_all(httpHeader,strlen(httpHeader));
+            clientSocketConn.send_all(httpHeader,strlen(httpHeader));
             // MIME type
             char *pDot = strrchr(filename, '.');
             char mimeType[MAX_MIMETYPE_LEN+1];
@@ -269,16 +327,16 @@
                 strcpy(mimeType, "Content-Type: text/css\r\n");
             if (pDot && !strcmp(pDot, ".js"))
                 strcpy(mimeType, "Content-Type: application/javascript\r\n");
-//            client.send_all(mimeType,strlen(mimeType));
+//            clientSocketConn.send_all(mimeType,strlen(mimeType));
             RD_INFO("MIME TYPE %s", mimeType);
             // Read file in blocks and send
             int rdCnt = 0;
             char fileBuf[1024];
             while ((rdCnt = fread(fileBuf, sizeof( char ), 1024, fp)) == 1024) 
             {
-                client.send_all(fileBuf, rdCnt);
+                clientSocketConn.send_all(fileBuf, rdCnt);
             }
-            client.send_all(fileBuf, rdCnt);
+            clientSocketConn.send_all(fileBuf, rdCnt);
             fclose(fp);
             closeConn = false;
         }
@@ -286,11 +344,13 @@
     return closeConn;
 }
 
-void RdWebServer::sendFromCache(RdFileCacheEntry* pCacheEntry, TCPSocketConnection &client, char* httpHeader)
+#ifdef SUPPORT_LOCAL_FILE_CACHE
+
+void RdWebServer::sendFromCache(RdFileCacheEntry* pCacheEntry, TCPSocketConnection &clientSocketConn, char* httpHeader)
 {
     RD_INFO("Sending file %s from cache %d bytes\r\n", pCacheEntry->_fileName, pCacheEntry->_nFileLen);
     sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
-    client.send_all(httpHeader,strlen(httpHeader));
+    clientSocketConn.send_all(httpHeader,strlen(httpHeader));
     char* pMem = pCacheEntry->_pFileContent;
     int nLenLeft = pCacheEntry->_nFileLen;
     int blkSize = 2048;
@@ -298,13 +358,14 @@
     {
         if (blkSize > nLenLeft)
             blkSize = nLenLeft;
-        client.send_all(pMem, blkSize);
+        clientSocketConn.send_all(pMem, blkSize);
         pMem += blkSize;
         nLenLeft -= blkSize;
     }
 }
+#endif
 
-void RdWebServer::handleLocalFileRequest(char* inFileName, char* argStr, TCPSocketConnection &client, char* httpHeader, bool bCacheIfPossible)
+void RdWebServer::handleLocalFileRequest(char* inFileName, char* argStr, TCPSocketConnection &clientSocketConn, char* httpHeader, bool bCacheIfPossible)
 {
 
 #ifdef SUPPORT_LOCAL_FILESYSTEM
@@ -327,7 +388,7 @@
             {
                 if ((*it)->_bCacheValid)
                 {
-                    sendFromCache(*it, client, httpHeader);
+                    sendFromCache(*it, clientSocketConn, httpHeader);
                     return;
                 }
                 bTryToCache = false; // don't try to cache as cacheing must have already failed
@@ -345,7 +406,7 @@
                 _cachedFiles.push_back(pCacheEntry);
                 if (bCacheSuccess)
                 {
-                    sendFromCache(pCacheEntry, client, httpHeader);
+                    sendFromCache(pCacheEntry, clientSocketConn, httpHeader);
                     return;
                 }
             }
@@ -359,21 +420,21 @@
     {
         RD_WARN("Local file %s not found\r\n", localFilename);
         sprintf(httpHeader,"HTTP/1.1 404 Not Found \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
-        client.send_all(httpHeader,strlen(httpHeader));
-        client.send_all(reqFileNameStr,strlen(reqFileNameStr));
+        clientSocketConn.send_all(httpHeader,strlen(httpHeader));
+        clientSocketConn.send_all(reqFileNameStr,strlen(reqFileNameStr));
     }
     else
     {
         RD_INFO("Sending file %s from disk\r\n", localFilename);
         sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
-        client.send_all(httpHeader,strlen(httpHeader));
+        clientSocketConn.send_all(httpHeader,strlen(httpHeader));
         int rdCnt = 0;
         char fileBuf[2000];
         while ((rdCnt = fread(fileBuf, sizeof( char ), 2000, fp)) == 2000) 
         {
-            client.send_all(fileBuf, rdCnt);
+            clientSocketConn.send_all(fileBuf, rdCnt);
         }
-        client.send_all(fileBuf, rdCnt);
+        clientSocketConn.send_all(fileBuf, rdCnt);
         fclose(fp);
     }
     
@@ -381,12 +442,14 @@
 
     RD_WARN("Local file system not supported\r\n");
     sprintf(httpHeader,"HTTP/1.1 404 Not Found \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
-    client.send_all(httpHeader,strlen(httpHeader));
-    client.send_all(inFileName,strlen(inFileName));
+    clientSocketConn.send_all(httpHeader,strlen(httpHeader));
+    clientSocketConn.send_all(inFileName,strlen(inFileName));
 
 #endif
 }
 
+#ifdef SUPPORT_LOCAL_FILE_CACHE
+
 bool RdFileCacheEntry::readLocalFileIntoCache(char* fileName)
 {
 #ifdef SUPPORT_LOCAL_FILESYSTEM
@@ -443,6 +506,8 @@
 #endif
 }
 
+#endif
+
 bool RdWebServer::extractCmdArgs(char* buf, char* pCmdStr, int maxCmdStrLen, char* pArgStr, int maxArgStrLen)
 {
     *pCmdStr = '\0';
--- a/RdWebServer.h	Tue May 05 15:05:44 2015 +0000
+++ b/RdWebServer.h	Tue May 05 20:27:33 2015 +0000
@@ -1,5 +1,5 @@
 /* RdWebServer.h
-   Rob Dobson 2013
+   Rob Dobson 2013-2015
    Inspired by Jasper Schuurmans multi-threaded web server for Netduino http://www.schuurmans.cc/multi-threaded-web-server-for-netduino-plus
 */
 #ifndef RD_WEB_SERVER
@@ -52,9 +52,12 @@
 
 //#define SUPPORT_LOCAL_FILESYSTEM 1
 //#define SUPPORT_FOLDER_VIEW 1
+//#define SUPPORT_LOCAL_FILE_CACHE 1
 
 extern RawSerial pc;
 
+#ifdef SUPPORT_LOCAL_FILE_CACHE
+
 class RdFileCacheEntry
 {
     public:
@@ -78,6 +81,8 @@
         int _nFileLen;
 };
 
+#endif
+
 typedef char* (*CmdCallbackType)(int method, char*cmdStr, char* argStr);
 
 class RdWebServerCmdDef
@@ -86,23 +91,27 @@
         static const int CMD_LOCALFILE = 1;
         static const int CMD_CALLBACK = 2;
         static const int CMD_SDORUSBFILE = 3;
-        RdWebServerCmdDef(char* pStr, int cmdType, CmdCallbackType callback, char* substFileName, bool bCacheIfPossible)
+        RdWebServerCmdDef(char* pStr, int cmdType, CmdCallbackType callback, char* subst8dot3FileName = NULL, bool bCacheIfPossible = false)
         {
             _pCmdStr = pStr;
             _cmdType = cmdType;
             _callback = callback;
-            _substFileName[0] = '\0';
-            if (substFileName != NULL)
+#ifdef SUPPORT_LOCAL_FILE_CACHE
+            _subst8dot3FileName[0] = '\0';
+            if (subst8dot3FileName != NULL)
             {
-                strncpy(_substFileName, substFileName, RdFileCacheEntry::CACHE_MAX_FNAME_LEN);
-                _substFileName[RdFileCacheEntry::CACHE_MAX_FNAME_LEN-1] = '\0';
+                strncpy(_subst8dot3FileName, subst8dot3FileName, RdFileCacheEntry::CACHE_MAX_FNAME_LEN);
+                _subst8dot3FileName[RdFileCacheEntry::CACHE_MAX_FNAME_LEN-1] = '\0';
             }
+#endif
             _bCacheIfPossible = bCacheIfPossible;
         };
         char* _pCmdStr;
         int _cmdType;
         CmdCallbackType _callback;
-        char _substFileName[RdFileCacheEntry::CACHE_MAX_FNAME_LEN];
+#ifdef SUPPORT_LOCAL_FILE_CACHE
+        char _subst8dot3FileName[RdFileCacheEntry::CACHE_MAX_FNAME_LEN];
+#endif
         bool _bCacheIfPossible;
 };
 
@@ -120,20 +129,17 @@
         
         bool init(int port, DigitalOut* pStatusLed, char* pBaseWebFolder);
         void run();
-        bool isListening()
-        {
-            return _serverIsListening;
-        };
-        
         void addCommand(char* pCmdStr, int cmdType, CmdCallbackType callback = NULL, char* substFileName = NULL, bool cacheIfPossible = false);
         
     private :
         int _port;
         DigitalOut* _pStatusLed;
-        TCPSocketServer _socketSrv;
-        bool _serverIsListening;
+        TCPSocketServer _serverSocket;
+        bool _initOk;
         std::vector<RdWebServerCmdDef*> _commands;
+#ifdef SUPPORT_LOCAL_FILE_CACHE
         std::vector<RdFileCacheEntry*> _cachedFiles;
+#endif
         bool extractCmdArgs(char* buf, char* pCmdStr, int maxCmdStrLen, char* pArgStr, int maxArgStrLen);
         char* _pBaseWebFolder;
         char _httpHeader[HTTPD_MAX_HDR_LENGTH+1];
@@ -142,7 +148,9 @@
         void handleLocalFileRequest(char* cmdStr, char* argStr, TCPSocketConnection &client, char* httpHeader, bool bCacheIfPossible);
         bool handleSDFileRequest(char* cmdStr, char* argStr, TCPSocketConnection &client, char* httpHeader);
         void handleCGIRequest(char* pUriStr, char* pQueryStr);
+#ifdef SUPPORT_LOCAL_FILE_CACHE
         void sendFromCache(RdFileCacheEntry* pCacheEntry, TCPSocketConnection &client, char* httpHeader);
+#endif
         bool handleReceivedHttp(TCPSocketConnection &client);
 
 };