webserver: update with latest upstream code
authorFrédéric Péters <fpeters@0d.be>
Wed, 26 Aug 2020 08:09:29 +0000 (10:09 +0200)
committerFrédéric Péters <fpeters@0d.be>
Thu, 25 Mar 2021 07:13:36 +0000 (08:13 +0100)
https://github.com/webduino/Webduino

WebServer.h

index 8647e091960d48de344d4adda12905240fca491e..4e25ce3e26bb1a6ba0eb5d6b3f1435dd784ff916 100644 (file)
 #define WEBDUINO_SERVER_ERROR_MESSAGE "<h1>500 Internal Server Error</h1>"
 #endif // WEBDUINO_SERVER_ERROR_MESSAGE
 
+#ifndef WEBDUINO_OUTPUT_BUFFER_SIZE
+#define WEBDUINO_OUTPUT_BUFFER_SIZE 32
+#endif // WEBDUINO_OUTPUT_BUFFER_SIZE
+
 // add '#define WEBDUINO_FAVICON_DATA ""' to your application
 // before including WebServer.h to send a null file as the favicon.ico file
 // otherwise this defaults to a 16x16 px black diode on blue ground
 extern "C" unsigned long millis(void);
 
 // declare a static string
+#ifdef __AVR__
 #define P(name)   static const unsigned char name[] PROGMEM
+#else
+#define P(name)   static const unsigned char name[]
+#endif
 
 // returns the number of elements in the array
 #define SIZE(array) (sizeof(array) / sizeof(*array))
 
+#ifdef _VARIANT_ARDUINO_DUE_X_
+#define pgm_read_byte(ptr) (unsigned char)(* ptr)
+#endif
 /********************************************************************
  * DECLARATIONS
  ********************************************************************/
@@ -140,11 +151,11 @@ extern "C" unsigned long millis(void);
  * when you call nextURLparam AFTER the last parameter is read.  The
  * last actual parameter gets an "OK" return code. */
 
-typedef enum URLPARAM_RESULT { URLPARAM_OK,
-                               URLPARAM_NAME_OFLO,
-                               URLPARAM_VALUE_OFLO,
-                               URLPARAM_BOTH_OFLO,
-                               URLPARAM_EOS         // No params left
+enum URLPARAM_RESULT { URLPARAM_OK,
+                       URLPARAM_NAME_OFLO,
+                       URLPARAM_VALUE_OFLO,
+                       URLPARAM_BOTH_OFLO,
+                       URLPARAM_EOS         // No params left
 };
 
 class WebServer: public Print
@@ -265,7 +276,7 @@ public:
 
   // output headers and a message indicating a server error
   void httpFail();
-  
+
   // output headers and a message indicating "401 Unauthorized"
   void httpUnauthorized();
 
@@ -288,9 +299,6 @@ public:
 
   // implementation of write used to implement Print interface
   virtual size_t write(uint8_t);
-  virtual size_t write(const char *str);
-  virtual size_t write(const uint8_t *buffer, size_t size);
-  size_t write(const char *data, size_t length);
 
   // tells if there is anything to process
   uint8_t available();
@@ -301,7 +309,7 @@ private:
   const char *m_urlPrefix;
 
   unsigned char m_pushback[32];
-  char m_pushbackDepth;
+  unsigned char m_pushbackDepth;
 
   int m_contentLength;
   char m_authCredentials[51];
@@ -314,9 +322,12 @@ private:
     const char *verb;
     Command *cmd;
   } m_commands[8];
-  char m_cmdCount;
+  unsigned char m_cmdCount;
   UrlPathCommand *m_urlPathCmd;
 
+  uint8_t m_buffer[WEBDUINO_OUTPUT_BUFFER_SIZE];
+  uint8_t m_bufFill;
+
   void reset();
   void getRequest(WebServer::ConnectionType &type, char *request, int *length);
   bool dispatchCommand(ConnectionType requestType, char *verb,
@@ -330,6 +341,7 @@ private:
                              char *url_tail, bool tail_complete);
   void noRobots(ConnectionType type);
   void favicon(ConnectionType type);
+  void flushBuf();
 };
 
 /* define this macro if you want to include the header in a sketch source
@@ -343,14 +355,15 @@ private:
 
 WebServer::WebServer(const char *urlPrefix, int port) :
   m_server(port),
-  m_client(255),
+  m_client(MAX_SOCK_NUM),
   m_urlPrefix(urlPrefix),
   m_pushbackDepth(0),
-  m_cmdCount(0),
   m_contentLength(0),
   m_failureCmd(&defaultFailCmd),
   m_defaultCmd(&defaultFailCmd),
-  m_urlPathCmd(NULL)
+  m_cmdCount(0),
+  m_urlPathCmd(NULL),
+  m_bufFill(0)
 {
 }
 
@@ -385,80 +398,59 @@ void WebServer::setUrlPathCommand(UrlPathCommand *cmd)
 
 size_t WebServer::write(uint8_t ch)
 {
-  return m_client.write(ch);
-}
+  m_buffer[m_bufFill++] = ch;
 
-size_t WebServer::write(const char *str)
-{
-  return m_client.write(str);
-}
+  if(m_bufFill == sizeof(m_buffer))
+  {
+    m_client.write(m_buffer, sizeof(m_buffer));
+    m_bufFill = 0;
+  }
 
-size_t WebServer::write(const uint8_t *buffer, size_t size)
-{
-  return m_client.write(buffer, size);
+  return sizeof(ch);
 }
 
-size_t WebServer::write(const char *buffer, size_t length)
+void WebServer::flushBuf()
 {
-  return m_client.write((const uint8_t *)buffer, length);
+  if(m_bufFill > 0)
+  {
+    m_client.write(m_buffer, m_bufFill);
+    m_bufFill = 0;
+  }
 }
 
 void WebServer::writeP(const unsigned char *data, size_t length)
 {
-  // copy data out of program memory into local storage, write out in
-  // chunks of 32 bytes to avoid extra short TCP/IP packets
-  uint8_t buffer[32];
-  size_t bufferEnd = 0;
+  // copy data out of program memory into local storage
 
   while (length--)
   {
-    if (bufferEnd == 32)
-    {
-      m_client.write(buffer, 32);
-      bufferEnd = 0;
-    }
-
-    buffer[bufferEnd++] = pgm_read_byte(data++);
+    write(pgm_read_byte(data++));
   }
-
-  if (bufferEnd > 0)
-    m_client.write(buffer, bufferEnd);
 }
 
 void WebServer::printP(const unsigned char *str)
 {
-  // copy data out of program memory into local storage, write out in
-  // chunks of 32 bytes to avoid extra short TCP/IP packets
-  uint8_t buffer[32];
-  size_t bufferEnd = 0;
-  
-  while (buffer[bufferEnd++] = pgm_read_byte(str++))
+  // copy data out of program memory into local storage
+
+  while (uint8_t value = pgm_read_byte(str++))
   {
-    if (bufferEnd == 32)
-    {
-      m_client.write(buffer, 32);
-      bufferEnd = 0;
-    }
+    write(value);
   }
-
-  // write out everything left but trailing NUL
-  if (bufferEnd > 1)
-    m_client.write(buffer, bufferEnd - 1);
 }
 
 void WebServer::printCRLF()
 {
-  m_client.write((const uint8_t *)"\r\n", 2);
+  print(CRLF);
 }
 
 bool WebServer::dispatchCommand(ConnectionType requestType, char *verb,
         bool tail_complete)
 {
-  // if there is no URL, i.e. we have a prefix and it's requested without a 
+  // if there is no URL, i.e. we have a prefix and it's requested without a
   // trailing slash or if the URL is just the slash
   if ((verb[0] == 0) || ((verb[0] == '/') && (verb[1] == 0)))
   {
-    m_defaultCmd(*this, requestType, "", tail_complete);
+    m_defaultCmd(*this, requestType, (char*)"", tail_complete);
     return true;
   }
   // if the URL is just a slash followed by a question mark
@@ -473,9 +465,9 @@ bool WebServer::dispatchCommand(ConnectionType requestType, char *verb,
   // if the first character is a slash,  there's more after it.
   if (verb[0] == '/')
   {
-    char i;
+    unsigned char i;
     char *qm_loc;
-    int verb_len;
+    unsigned int verb_len;
     int qm_offset;
     // Skip over the leading "/",  because it makes the code more
     // efficient and easier to understand.
@@ -596,6 +588,8 @@ void WebServer::processConnection(char *buff, int *bufflen)
       m_failureCmd(*this, requestType, buff, (*bufflen) >= 0);
     }
 
+    flushBuf();
+
 #if WEBDUINO_SERIAL_DEBUGGING > 1
     Serial.println("*** stopping connection ***");
 #endif
@@ -606,7 +600,7 @@ void WebServer::processConnection(char *buff, int *bufflen)
 bool WebServer::checkCredentials(const char authCredentials[45])
 {
   char basic[7] = "Basic ";
-  if((0 == strncmp(m_authCredentials,basic,6)) && 
+  if((0 == strncmp(m_authCredentials,basic,6)) &&
      (0 == strcmp(authCredentials, m_authCredentials + 6))) return true;
   return false;
 }
@@ -719,7 +713,7 @@ void WebServer::httpSeeOther(const char *otherURL)
 
 int WebServer::read()
 {
-  if (m_client == NULL)
+  if (!m_client)
     return -1;
 
   if (m_pushbackDepth == 0)
@@ -1033,7 +1027,7 @@ URLPARAM_RESULT WebServer::nextURLparam(char **tail, char *name, int nameLen,
       *name++ = ch;
       --nameLen;
     }
-    else
+    else if(keep_scanning)
       result = URLPARAM_NAME_OFLO;
   }
 
@@ -1089,7 +1083,7 @@ URLPARAM_RESULT WebServer::nextURLparam(char **tail, char *name, int nameLen,
         *value++ = ch;
         --valueLen;
       }
-      else
+      else if(keep_scanning)
         result = (result == URLPARAM_OK) ?
           URLPARAM_VALUE_OFLO :
           URLPARAM_BOTH_OFLO;
@@ -1161,7 +1155,7 @@ void WebServer::getRequest(WebServer::ConnectionType &type,
 
 void WebServer::processHeaders()
 {
-  // look for three things: the Content-Length header, the Authorization 
+  // look for three things: the Content-Length header, the Authorization
   // header, and the double-CRLF that ends the headers.
 
   // empty the m_authCredentials before every run of this function.