Rob Dobson / RdWebServer

Dependents:   RdBlindsServer SpideyWallWeb RdGasUseMonitor

Files at this revision

API Documentation at this revision

Comitter:
Bobty
Date:
Tue May 05 15:05:44 2015 +0000
Parent:
13:4f9c09d3da13
Child:
15:0865fa4b046a
Commit message:
Improving robustness

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	Mon May 04 17:26:32 2015 +0000
+++ b/RdWebServer.cpp	Tue May 05 15:05:44 2015 +0000
@@ -11,6 +11,7 @@
 #define MAX_CMDSTR_LEN 100
 #define MAX_ARGSTR_LEN 100
 #define MAX_FILENAME_LEN (MAX_ARGSTR_LEN + 20)
+#define MAX_MIMETYPE_LEN 50
 
 RdWebServer::RdWebServer()
 {
@@ -58,8 +59,9 @@
     return true;
 }
 
-void RdWebServer::handleReceivedHttp(TCPSocketConnection &client)
+bool RdWebServer::handleReceivedHttp(TCPSocketConnection &client)
 {
+    bool closeConn = true;
     RD_DBG("Received Data: %d\n\r\n\r%.*s\n\r",strlen(_buffer),strlen(_buffer),_buffer);
     int method = METHOD_OTHER;
     if (strncmp(_buffer, "GET ", 4) == 0)
@@ -84,7 +86,7 @@
                 if ((*it)->_cmdType == RdWebServerCmdDef::CMD_CALLBACK)
                 {
                     char* respStr = ((*it)->_callback)(method, cmdStr, argStr);
-                    client.send(respStr, strlen(respStr));
+                    client.send_all(respStr, strlen(respStr));
                 }
                 else if ((*it)->_cmdType == RdWebServerCmdDef::CMD_LOCALFILE)
                 {
@@ -109,11 +111,11 @@
                         strcpy(combinedFileName, (*it)->_substFileName);
                         if (combinedFileName[strlen(combinedFileName)-1] == '*')
                             strcpy(combinedFileName+strlen(combinedFileName)-1, argStr);
-                        handleSDFileRequest(combinedFileName, argStr, client, _httpHeader);
+                        closeConn = handleSDFileRequest(combinedFileName, argStr, client, _httpHeader);
                     }
                     else
                     {
-                        handleSDFileRequest(cmdStr, argStr, client, _httpHeader);
+                        closeConn = handleSDFileRequest(cmdStr, argStr, client, _httpHeader);
                     }
                 }
                 break;
@@ -121,8 +123,9 @@
         }
         // If command not found see if it is a local file
         if (!cmdFound)
-            handleSDFileRequest(cmdStr, argStr, client, _httpHeader);
+            closeConn = handleSDFileRequest(cmdStr, argStr, client, _httpHeader);
     }
+    return closeConn;
 }
 
 void RdWebServer::run()
@@ -164,22 +167,27 @@
                 else if (rxLen == 0)
                 {
                     RD_WARN("received buffer is empty.\n\r");
-                    continue;                
+                    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(_httpHeader,strlen(_httpHeader));
-                    client.send(_buffer, rxLen);
-                    continue;
+                    client.send_all(_httpHeader,strlen(_httpHeader));
+                    client.send_all(_buffer, rxLen);
+                    break;
                 }
                 _buffer[rxLen] = '\0';
     
                 // Handle buffer
-                handleReceivedHttp(client);
-                
-                // Done
-                break;
+                if (handleReceivedHttp(client))
+                {
+                    break;
+                }
+                else
+                {
+                    connectLimitTimer.reset();
+                    connectLimitTimer.start();
+                }
             }
             
             // Connection now closed
@@ -197,8 +205,9 @@
     _commands.push_back(new RdWebServerCmdDef(pCmdStr, cmdType, callback, substFileName, cacheIfPossible));
 }
 
-void RdWebServer::handleSDFileRequest(char* inFileName, char* argStr, TCPSocketConnection &client, char* httpHeader)
+bool RdWebServer::handleSDFileRequest(char* inFileName, char* argStr, TCPSocketConnection &client, char* httpHeader)
 {
+    bool closeConn = true;
     const int HTTPD_MAX_FNAME_LENGTH = 127;
     char filename[HTTPD_MAX_FNAME_LENGTH+1];
     
@@ -213,21 +222,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(httpHeader,strlen(httpHeader));
+            client.send_all(httpHeader,strlen(httpHeader));
             sprintf(httpHeader,"<html><head><title>Directory Listing</title></head><body><h1>%s</h1><ul>", inFileName);
-            client.send(httpHeader,strlen(httpHeader));
+            client.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(httpHeader,strlen(httpHeader));
+                client.send_all(httpHeader,strlen(httpHeader));
             }
         }
         closedir(d);
         RD_DBG("Directory closed\n");
         sprintf(httpHeader,"</ul></body></html>");
-        client.send(httpHeader,strlen(httpHeader));
+        client.send_all(httpHeader,strlen(httpHeader));
     }
     else
 #endif
@@ -239,32 +248,49 @@
         if (fp == NULL)
         {
             RD_WARN("Filename %s not found\r\n", filename);
-            sprintf(httpHeader,"HTTP/1.1 404 Not Found \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
-            client.send(httpHeader,strlen(httpHeader));
-            client.send(inFileName,strlen(inFileName));
+            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));
+            closeConn = false;
         }
         else
         {
             RD_INFO("Sending file %s\r\n", filename);
-            sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
-            client.send(httpHeader,strlen(httpHeader));
+            fseek(fp, 0L, SEEK_END);
+            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));
+            // MIME type
+            char *pDot = strrchr(filename, '.');
+            char mimeType[MAX_MIMETYPE_LEN+1];
+            if (pDot && (!strcmp(pDot, ".html") || !strcmp(pDot, ".htm")))
+                strcpy(mimeType, "Content-Type: text/html\r\n");
+            else if (pDot && !strcmp(pDot, ".css"))
+                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));
+            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);
             }
-            client.send(fileBuf, rdCnt);
+            client.send_all(fileBuf, rdCnt);
             fclose(fp);
+            closeConn = false;
         }
     }
+    return closeConn;
 }
 
 void RdWebServer::sendFromCache(RdFileCacheEntry* pCacheEntry, TCPSocketConnection &client, 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(httpHeader,strlen(httpHeader));
+    client.send_all(httpHeader,strlen(httpHeader));
     char* pMem = pCacheEntry->_pFileContent;
     int nLenLeft = pCacheEntry->_nFileLen;
     int blkSize = 2048;
@@ -333,14 +359,14 @@
     {
         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(httpHeader,strlen(httpHeader));
-        client.send(reqFileNameStr,strlen(reqFileNameStr));
+        client.send_all(httpHeader,strlen(httpHeader));
+        client.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(httpHeader,strlen(httpHeader));
+        client.send_all(httpHeader,strlen(httpHeader));
         int rdCnt = 0;
         char fileBuf[2000];
         while ((rdCnt = fread(fileBuf, sizeof( char ), 2000, fp)) == 2000) 
@@ -355,7 +381,7 @@
 
     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(httpHeader,strlen(httpHeader));
+    client.send_all(httpHeader,strlen(httpHeader));
     client.send_all(inFileName,strlen(inFileName));
 
 #endif
--- a/RdWebServer.h	Mon May 04 17:26:32 2015 +0000
+++ b/RdWebServer.h	Tue May 05 15:05:44 2015 +0000
@@ -140,10 +140,10 @@
         char _buffer[HTTPD_MAX_REQ_LENGTH+1];
 
         void handleLocalFileRequest(char* cmdStr, char* argStr, TCPSocketConnection &client, char* httpHeader, bool bCacheIfPossible);
-        void handleSDFileRequest(char* cmdStr, char* argStr, TCPSocketConnection &client, char* httpHeader);
+        bool handleSDFileRequest(char* cmdStr, char* argStr, TCPSocketConnection &client, char* httpHeader);
         void handleCGIRequest(char* pUriStr, char* pQueryStr);
         void sendFromCache(RdFileCacheEntry* pCacheEntry, TCPSocketConnection &client, char* httpHeader);
-        void handleReceivedHttp(TCPSocketConnection &client);
+        bool handleReceivedHttp(TCPSocketConnection &client);
 
 };