#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
********************************************************************/
* 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
// output headers and a message indicating a server error
void httpFail();
-
+
// output headers and a message indicating "401 Unauthorized"
void httpUnauthorized();
// 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();
const char *m_urlPrefix;
unsigned char m_pushback[32];
- char m_pushbackDepth;
+ unsigned char m_pushbackDepth;
int m_contentLength;
char m_authCredentials[51];
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,
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
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)
{
}
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
// 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.
m_failureCmd(*this, requestType, buff, (*bufflen) >= 0);
}
+ flushBuf();
+
#if WEBDUINO_SERIAL_DEBUGGING > 1
Serial.println("*** stopping connection ***");
#endif
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;
}
int WebServer::read()
{
- if (m_client == NULL)
+ if (!m_client)
return -1;
if (m_pushbackDepth == 0)
*name++ = ch;
--nameLen;
}
- else
+ else if(keep_scanning)
result = URLPARAM_NAME_OFLO;
}
*value++ = ch;
--valueLen;
}
- else
+ else if(keep_scanning)
result = (result == URLPARAM_OK) ?
URLPARAM_VALUE_OFLO :
URLPARAM_BOTH_OFLO;
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.