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.

Committer:
Bobty
Date:
Fri Oct 16 08:41:02 2015 +0000
Revision:
27:0c2d6f598ae5
Parent:
26:3c4c10e989b1
Child:
28:99036ff32459
Re-enabled folder view by default

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bobty 20:e6c7db867593 1 // RdWebServer - Simple Web Server for MBED
Bobty 20:e6c7db867593 2 // Copyright (C) Rob Dobson 2013-2015, MIT License
Bobty 20:e6c7db867593 3 // Inspired by Jasper Schuurmans multi-threaded web server for Netduino which now seems to have gone from ...
Bobty 20:e6c7db867593 4 // http://www.schuurmans.cc/multi-threaded-web-server-for-netduino-plus
Bobty 20:e6c7db867593 5 // More details at http://robdobson.com/2013/10/moving-my-window-shades-control-to-mbed/
Bobty 3:594136d34a32 6
Bobty 18:5de680c4cfcb 7 // Setting RDWEB_DEBUG to 4 causes all debugging to be shown
Bobty 21:2dfb56648b93 8 #define RDWEB_DEBUG 2
Bobty 18:5de680c4cfcb 9
Bobty 18:5de680c4cfcb 10 // Change the settings below to support a local file system (not available on some MBEDs)
Bobty 21:2dfb56648b93 11 #define SUPPORT_LOCAL_FILESYSTEM 1
Bobty 21:2dfb56648b93 12 #define SUPPORT_LOCAL_FILE_CACHE 1
Bobty 18:5de680c4cfcb 13
Bobty 18:5de680c4cfcb 14 // Change this to support display of files on the server
Bobty 27:0c2d6f598ae5 15 #define SUPPORT_FOLDER_VIEW 1
Bobty 12:c14ffd4ec125 16
Bobty 0:b5b4d07f7827 17 #include "RdWebServer.h"
Bobty 0:b5b4d07f7827 18
Bobty 18:5de680c4cfcb 19 // Limits - note particularly the MAX_FILENAME_LEN
Bobty 15:0865fa4b046a 20 const int MAX_FILENAME_LEN = (MAX_ARGSTR_LEN + 20);
Bobty 1:75bb184de749 21
Bobty 18:5de680c4cfcb 22 // Constructor
Bobty 26:3c4c10e989b1 23 RdWebServer::RdWebServer(Mutex* pSdCardMutex)
Bobty 0:b5b4d07f7827 24 {
Bobty 15:0865fa4b046a 25 _initOk = false;
Bobty 0:b5b4d07f7827 26 _pStatusLed = NULL;
Bobty 24:27800de38eab 27 _curSplitPayloadPos = -1;
Bobty 24:27800de38eab 28 _curCmdStr[0] = 0;
Bobty 24:27800de38eab 29 _curArgStr[0] = 0;
Bobty 24:27800de38eab 30 _bufferReceivedLen = 0;
Bobty 24:27800de38eab 31 _curContentLen = -1;
Bobty 24:27800de38eab 32 _curHttpMethod = METHOD_OTHER;
Bobty 24:27800de38eab 33 _curWebServerCmdDef = NULL;
Bobty 26:3c4c10e989b1 34 _pSdCardMutex = pSdCardMutex;
Bobty 0:b5b4d07f7827 35 }
Bobty 0:b5b4d07f7827 36
Bobty 18:5de680c4cfcb 37 // Destructor
Bobty 0:b5b4d07f7827 38 RdWebServer::~RdWebServer()
Bobty 0:b5b4d07f7827 39 {
Bobty 2:9d8793c23b46 40 // Clean-up - probably never called as we're on a microcontroller!
Bobty 2:9d8793c23b46 41 for (std::vector<RdWebServerCmdDef*>::iterator it = _commands.begin() ; it != _commands.end(); ++it)
Bobty 2:9d8793c23b46 42 delete (*it);
Bobty 0:b5b4d07f7827 43 }
Bobty 0:b5b4d07f7827 44
Bobty 18:5de680c4cfcb 45 // Init
Bobty 4:6afb3bbf20a4 46 bool RdWebServer::init(int port, DigitalOut* pStatusLed, char* pBaseWebFolder)
Bobty 0:b5b4d07f7827 47 {
Bobty 15:0865fa4b046a 48 // Settings
Bobty 0:b5b4d07f7827 49 _port = port;
Bobty 0:b5b4d07f7827 50 _pStatusLed = pStatusLed;
Bobty 4:6afb3bbf20a4 51 _pBaseWebFolder = pBaseWebFolder;
Bobty 0:b5b4d07f7827 52
Bobty 23:0fc3d7b5e596 53 // Non-blocking by default
Bobty 23:0fc3d7b5e596 54 _blockingOnAccept = false;
Bobty 23:0fc3d7b5e596 55 _blockingOnReceive = false;
Bobty 17:080f2bed8b36 56
Bobty 17:080f2bed8b36 57 // This is the same as the default in the socket.cpp file
Bobty 17:080f2bed8b36 58 _timeoutOnBlocking = 1500;
Bobty 17:080f2bed8b36 59
Bobty 17:080f2bed8b36 60 // If closeConnAfterSend is set false then the socket connection remains open and only
Bobty 23:0fc3d7b5e596 61 // one client can access the server until a time-out occurs - this should be ok for most applications
Bobty 23:0fc3d7b5e596 62 _closeConnAfterSend = false;
Bobty 17:080f2bed8b36 63 _closeConnOnReceiveFail = true;
Bobty 17:080f2bed8b36 64
Bobty 15:0865fa4b046a 65 // Setup tcp socket
Bobty 15:0865fa4b046a 66 if(_serverSocket.bind(port)< 0)
Bobty 0:b5b4d07f7827 67 {
Bobty 19:f67ac231b570 68 RD_WARN("TCP server bind fail");
Bobty 0:b5b4d07f7827 69 return false;
Bobty 0:b5b4d07f7827 70 }
Bobty 23:0fc3d7b5e596 71
Bobty 23:0fc3d7b5e596 72 // Only one connection at a time as the server is single-threaded
Bobty 15:0865fa4b046a 73 if(_serverSocket.listen(1) < 0)
Bobty 0:b5b4d07f7827 74 {
Bobty 19:f67ac231b570 75 RD_WARN("TCP server listen fail");
Bobty 0:b5b4d07f7827 76 return false;
Bobty 0:b5b4d07f7827 77 }
Bobty 19:f67ac231b570 78 RD_INFO("TCP server is listening...");
Bobty 15:0865fa4b046a 79 _initOk = true;
Bobty 6:46285c519af2 80 return true;
Bobty 6:46285c519af2 81 }
Bobty 6:46285c519af2 82
Bobty 18:5de680c4cfcb 83 // Run - never returns so run in a thread
Bobty 15:0865fa4b046a 84 void RdWebServer::run()
Bobty 15:0865fa4b046a 85 {
Bobty 15:0865fa4b046a 86 // Check initialised ok
Bobty 15:0865fa4b046a 87 if (!_initOk)
Bobty 15:0865fa4b046a 88 return;
Bobty 15:0865fa4b046a 89
Bobty 15:0865fa4b046a 90 // Start accepting connections
Bobty 15:0865fa4b046a 91 while (true)
Bobty 15:0865fa4b046a 92 {
Bobty 15:0865fa4b046a 93 TCPSocketConnection clientSocketConn;
Bobty 15:0865fa4b046a 94 // Accept connection if available
Bobty 19:f67ac231b570 95 RD_INFO("Waiting for TCP connection");
Bobty 17:080f2bed8b36 96 clientSocketConn.set_blocking(_blockingOnAccept, _timeoutOnBlocking);
Bobty 15:0865fa4b046a 97 if(_serverSocket.accept(clientSocketConn)<0)
Bobty 15:0865fa4b046a 98 {
Bobty 19:f67ac231b570 99 RD_WARN("TCP Socket failed to accept connection");
Bobty 15:0865fa4b046a 100 continue;
Bobty 15:0865fa4b046a 101 }
Bobty 15:0865fa4b046a 102
Bobty 15:0865fa4b046a 103 // Connection
Bobty 19:f67ac231b570 104 RD_INFO("Connection from IP: %s", clientSocketConn.get_address());
Bobty 15:0865fa4b046a 105 if (_pStatusLed != NULL)
Bobty 15:0865fa4b046a 106 *_pStatusLed = true;
Bobty 15:0865fa4b046a 107
Bobty 15:0865fa4b046a 108 // While connected
Bobty 15:0865fa4b046a 109 bool forcedClosed = false;
Bobty 24:27800de38eab 110 _curSplitPayloadPos = -1;
Bobty 15:0865fa4b046a 111 while(clientSocketConn.is_connected() && !forcedClosed)
Bobty 15:0865fa4b046a 112 {
Bobty 15:0865fa4b046a 113 // Receive data
Bobty 23:0fc3d7b5e596 114 if (_blockingOnReceive != _blockingOnAccept)
Bobty 23:0fc3d7b5e596 115 clientSocketConn.set_blocking(_blockingOnReceive, _timeoutOnBlocking);
Bobty 15:0865fa4b046a 116 int rxLen = clientSocketConn.receive(_buffer, HTTPD_MAX_REQ_LENGTH);
Bobty 15:0865fa4b046a 117 if (rxLen == -1)
Bobty 15:0865fa4b046a 118 {
Bobty 17:080f2bed8b36 119 if (_closeConnOnReceiveFail)
Bobty 15:0865fa4b046a 120 {
Bobty 15:0865fa4b046a 121 int closeRet = clientSocketConn.close();
Bobty 25:ffa1dddd3da4 122 RD_DBG("Rx Timeout - conn close() ret %d (is_connected %d)", closeRet, clientSocketConn.is_connected());
Bobty 15:0865fa4b046a 123 forcedClosed = true;
Bobty 15:0865fa4b046a 124 }
Bobty 25:ffa1dddd3da4 125 else
Bobty 25:ffa1dddd3da4 126 {
Bobty 25:ffa1dddd3da4 127 RD_DBG("Rx Timeout - not closing - is_connected %d", clientSocketConn.is_connected());
Bobty 25:ffa1dddd3da4 128 }
Bobty 15:0865fa4b046a 129 continue;
Bobty 15:0865fa4b046a 130 }
Bobty 15:0865fa4b046a 131 if (rxLen == 0)
Bobty 15:0865fa4b046a 132 {
Bobty 19:f67ac231b570 133 RD_DBG("clientSocketConn.receive() returned %d - ignoring - is connected %d", rxLen, clientSocketConn.is_connected());
Bobty 15:0865fa4b046a 134 continue;
Bobty 15:0865fa4b046a 135 }
Bobty 18:5de680c4cfcb 136
Bobty 18:5de680c4cfcb 137 // Handle received message
Bobty 15:0865fa4b046a 138 _buffer[rxLen] = '\0';
Bobty 24:27800de38eab 139 _bufferReceivedLen = rxLen;
Bobty 24:27800de38eab 140 handleReceivedHttp(clientSocketConn);
Bobty 15:0865fa4b046a 141
Bobty 17:080f2bed8b36 142 // Close connection if required
Bobty 17:080f2bed8b36 143 if (_closeConnAfterSend)
Bobty 15:0865fa4b046a 144 {
Bobty 15:0865fa4b046a 145 int closeRet = clientSocketConn.close();
Bobty 19:f67ac231b570 146 RD_DBG("After send connection close() ret %d is connected %d", closeRet, clientSocketConn.is_connected());
Bobty 16:0248bbfdb6c1 147 forcedClosed = true;
Bobty 15:0865fa4b046a 148 }
Bobty 15:0865fa4b046a 149 }
Bobty 15:0865fa4b046a 150 }
Bobty 15:0865fa4b046a 151 }
Bobty 18:5de680c4cfcb 152
Bobty 18:5de680c4cfcb 153 // Handle a request
Bobty 15:0865fa4b046a 154 bool RdWebServer::handleReceivedHttp(TCPSocketConnection &clientSocketConn)
Bobty 6:46285c519af2 155 {
Bobty 17:080f2bed8b36 156 bool handledOk = false;
Bobty 24:27800de38eab 157
Bobty 24:27800de38eab 158 // Check for split payload
Bobty 24:27800de38eab 159 if (_curSplitPayloadPos != -1)
Bobty 24:27800de38eab 160 {
Bobty 24:27800de38eab 161 // Handle remaining parts of content
Bobty 24:27800de38eab 162 char* respStr = (_curWebServerCmdDef->_callback)(_curHttpMethod, _curCmdStr, _curArgStr, _buffer, _bufferReceivedLen,
Bobty 24:27800de38eab 163 _curContentLen, (unsigned char*)_buffer, _bufferReceivedLen, _curSplitPayloadPos);
Bobty 24:27800de38eab 164 RD_DBG("Received part of message - content %d - rx %d - splitAfter %d", _curContentLen, _bufferReceivedLen, _curSplitPayloadPos);
Bobty 24:27800de38eab 165 _curSplitPayloadPos += _bufferReceivedLen;
Bobty 24:27800de38eab 166 // Check if all received
Bobty 24:27800de38eab 167 if (_curSplitPayloadPos >= _curContentLen)
Bobty 24:27800de38eab 168 {
Bobty 24:27800de38eab 169 _curSplitPayloadPos = -1;
Bobty 24:27800de38eab 170 clientSocketConn.send_all(respStr, strlen(respStr));
Bobty 24:27800de38eab 171 RD_DBG("That was the end of message - content %d - rx %d", _curContentLen, _bufferReceivedLen);
Bobty 24:27800de38eab 172 }
Bobty 24:27800de38eab 173 return true;
Bobty 24:27800de38eab 174 }
Bobty 24:27800de38eab 175
Bobty 24:27800de38eab 176 // Get payload information
Bobty 24:27800de38eab 177 int payloadLen = -1;
Bobty 24:27800de38eab 178 unsigned char* pPayload = getPayloadDataFromMsg(_buffer, _bufferReceivedLen, payloadLen);
Bobty 24:27800de38eab 179
Bobty 24:27800de38eab 180 // Debug
Bobty 24:27800de38eab 181 int displayLen = _bufferReceivedLen;
Bobty 24:27800de38eab 182 if (payloadLen > 0)
Bobty 24:27800de38eab 183 displayLen = _bufferReceivedLen-payloadLen;
Bobty 24:27800de38eab 184 RD_DBG("\r\nNEW REQUEST RxLen %d ContentLen %d PayloadLen %d\n\r\n\r%.*s", _bufferReceivedLen, _curContentLen, payloadLen, displayLen, _buffer);
Bobty 24:27800de38eab 185
Bobty 24:27800de38eab 186 // Get HTTP method
Bobty 24:27800de38eab 187 _curHttpMethod = METHOD_OTHER;
Bobty 6:46285c519af2 188 if (strncmp(_buffer, "GET ", 4) == 0)
Bobty 24:27800de38eab 189 _curHttpMethod = METHOD_GET;
Bobty 23:0fc3d7b5e596 190 else if (strncmp(_buffer, "POST", 4) == 0)
Bobty 24:27800de38eab 191 _curHttpMethod = METHOD_POST;
Bobty 23:0fc3d7b5e596 192 else if (strncmp(_buffer, "OPTIONS", 7) == 0)
Bobty 24:27800de38eab 193 _curHttpMethod = METHOD_OPTIONS;
Bobty 7:fe7c33f7fbb8 194
Bobty 24:27800de38eab 195 // See if there is a valid HTTP command
Bobty 24:27800de38eab 196 _curContentLen = -1;
Bobty 24:27800de38eab 197 if (extractCmdArgs(_buffer+3, _curCmdStr, MAX_CMDSTR_LEN, _curArgStr, MAX_ARGSTR_LEN, _curContentLen))
Bobty 6:46285c519af2 198 {
Bobty 24:27800de38eab 199 RD_DBG("CmdStr %s", _curCmdStr);
Bobty 24:27800de38eab 200 RD_DBG("ArgStr %s", _curArgStr);
Bobty 24:27800de38eab 201
Bobty 7:fe7c33f7fbb8 202 bool cmdFound = false;
Bobty 7:fe7c33f7fbb8 203 for (std::vector<RdWebServerCmdDef*>::iterator it = _commands.begin() ; it != _commands.end(); ++it)
Bobty 6:46285c519af2 204 {
Bobty 24:27800de38eab 205 if (strcasecmp((*it)->_pCmdStr, _curCmdStr) == 0)
Bobty 24:27800de38eab 206 {
Bobty 24:27800de38eab 207 RD_DBG("FoundCmd <%s> Type %d", _curCmdStr, (*it)->_cmdType);
Bobty 7:fe7c33f7fbb8 208 cmdFound = true;
Bobty 7:fe7c33f7fbb8 209 if ((*it)->_cmdType == RdWebServerCmdDef::CMD_CALLBACK)
Bobty 7:fe7c33f7fbb8 210 {
Bobty 24:27800de38eab 211 char* respStr = ((*it)->_callback)(_curHttpMethod, _curCmdStr, _curArgStr, _buffer, _bufferReceivedLen,
Bobty 24:27800de38eab 212 _curContentLen, pPayload, payloadLen, 0);
Bobty 24:27800de38eab 213 // Handle split-payload situation
Bobty 24:27800de38eab 214 if (_curContentLen > 0 && payloadLen < _curContentLen)
Bobty 24:27800de38eab 215 {
Bobty 24:27800de38eab 216 _curSplitPayloadPos = payloadLen;
Bobty 24:27800de38eab 217 _curWebServerCmdDef = (*it);
Bobty 24:27800de38eab 218 }
Bobty 24:27800de38eab 219 else
Bobty 24:27800de38eab 220 {
Bobty 24:27800de38eab 221 clientSocketConn.send_all(respStr, strlen(respStr));
Bobty 24:27800de38eab 222 }
Bobty 24:27800de38eab 223 handledOk = true;
Bobty 6:46285c519af2 224 }
Bobty 17:080f2bed8b36 225 else if ( ((*it)->_cmdType == RdWebServerCmdDef::CMD_LOCALFILE) ||
Bobty 17:080f2bed8b36 226 ((*it)->_cmdType == RdWebServerCmdDef::CMD_SDORUSBFILE) )
Bobty 7:fe7c33f7fbb8 227 {
Bobty 17:080f2bed8b36 228 char combinedFileName[MAX_FILENAME_LEN];
Bobty 17:080f2bed8b36 229 strcpy(combinedFileName, (*it)->_substFileName);
Bobty 17:080f2bed8b36 230 if (strlen(combinedFileName) == 0)
Bobty 24:27800de38eab 231 strcpy(combinedFileName, _curCmdStr);
Bobty 17:080f2bed8b36 232 else if (combinedFileName[strlen(combinedFileName)-1] == '*')
Bobty 24:27800de38eab 233 strcpy(combinedFileName+strlen(combinedFileName)-1, _curArgStr);
Bobty 17:080f2bed8b36 234 if ((*it)->_cmdType == RdWebServerCmdDef::CMD_LOCALFILE)
Bobty 24:27800de38eab 235 handledOk = handleLocalFileRequest(combinedFileName, _curArgStr, clientSocketConn, (*it)->_bCacheIfPossible);
Bobty 7:fe7c33f7fbb8 236 else
Bobty 24:27800de38eab 237 handledOk = handleSDFileRequest(combinedFileName, _curArgStr, clientSocketConn);
Bobty 17:080f2bed8b36 238
Bobty 7:fe7c33f7fbb8 239 }
Bobty 7:fe7c33f7fbb8 240 break;
Bobty 6:46285c519af2 241 }
Bobty 6:46285c519af2 242 }
Bobty 7:fe7c33f7fbb8 243 // If command not found see if it is a local file
Bobty 7:fe7c33f7fbb8 244 if (!cmdFound)
Bobty 17:080f2bed8b36 245 {
Bobty 17:080f2bed8b36 246 char combinedFileName[MAX_FILENAME_LEN];
Bobty 24:27800de38eab 247 strcpy(combinedFileName, _curCmdStr);
Bobty 25:ffa1dddd3da4 248 if (strlen(_curArgStr) > 0)
Bobty 25:ffa1dddd3da4 249 {
Bobty 25:ffa1dddd3da4 250 strcat(combinedFileName, "/");
Bobty 25:ffa1dddd3da4 251 strcat(combinedFileName, _curArgStr);
Bobty 25:ffa1dddd3da4 252 }
Bobty 24:27800de38eab 253 handledOk = handleSDFileRequest(combinedFileName, _curArgStr, clientSocketConn);
Bobty 17:080f2bed8b36 254 }
Bobty 6:46285c519af2 255 }
Bobty 24:27800de38eab 256 else
Bobty 24:27800de38eab 257 {
Bobty 24:27800de38eab 258 RD_DBG("Cannot find command or args\r\n");
Bobty 24:27800de38eab 259 }
Bobty 17:080f2bed8b36 260 return handledOk;
Bobty 6:46285c519af2 261 }
Bobty 6:46285c519af2 262
Bobty 18:5de680c4cfcb 263 // Add a command to the server
Bobty 6:46285c519af2 264 void RdWebServer::addCommand(char* pCmdStr, int cmdType, CmdCallbackType callback, char* substFileName, bool cacheIfPossible)
Bobty 6:46285c519af2 265 {
Bobty 6:46285c519af2 266 _commands.push_back(new RdWebServerCmdDef(pCmdStr, cmdType, callback, substFileName, cacheIfPossible));
Bobty 6:46285c519af2 267 }
Bobty 6:46285c519af2 268
Bobty 18:5de680c4cfcb 269 // Form a header to respond
Bobty 17:080f2bed8b36 270 void RdWebServer::formHTTPHeader(const char* rsltCode, const char* contentType, int contentLen)
Bobty 17:080f2bed8b36 271 {
Bobty 23:0fc3d7b5e596 272 const char* closeConnStr = "\r\nConnection: keep-alive";
Bobty 17:080f2bed8b36 273 if(contentLen != -1)
Bobty 22:598a21373539 274 sprintf(_httpHeader, "HTTP/1.1 %s\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: %s\r\nContent-Length: %d%s\r\n\r\n", rsltCode, contentType, contentLen, _closeConnAfterSend ? closeConnStr : "");
Bobty 17:080f2bed8b36 275 else
Bobty 22:598a21373539 276 sprintf(_httpHeader, "HTTP/1.1 %s\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: %s%s\r\n\r\n", rsltCode, contentType, _closeConnAfterSend ? closeConnStr : "");
Bobty 17:080f2bed8b36 277 }
Bobty 18:5de680c4cfcb 278
Bobty 18:5de680c4cfcb 279 // Use file extension to determine MIME type
Bobty 17:080f2bed8b36 280 char* getMimeTypeStr(char* filename)
Bobty 6:46285c519af2 281 {
Bobty 17:080f2bed8b36 282 char* mimeType = "text/plain";
Bobty 17:080f2bed8b36 283 char *pDot = strrchr(filename, '.');
Bobty 17:080f2bed8b36 284 if (pDot && (!strcmp(pDot, ".html") || !strcmp(pDot, ".htm")))
Bobty 17:080f2bed8b36 285 mimeType = "text/html";
Bobty 17:080f2bed8b36 286 else if (pDot && !strcmp(pDot, ".css"))
Bobty 17:080f2bed8b36 287 mimeType = "text/css";
Bobty 17:080f2bed8b36 288 else if (pDot && !strcmp(pDot, ".js"))
Bobty 17:080f2bed8b36 289 mimeType = "application/javascript";
Bobty 17:080f2bed8b36 290 else if (pDot && !strcmp(pDot, ".png"))
Bobty 17:080f2bed8b36 291 mimeType = "image/png";
Bobty 17:080f2bed8b36 292 else if (pDot && (!strcmp(pDot, ".jpeg") || !strcmp(pDot, ".jpeg")))
Bobty 17:080f2bed8b36 293 mimeType = "image/jpeg";
Bobty 17:080f2bed8b36 294 return mimeType;
Bobty 17:080f2bed8b36 295 }
Bobty 18:5de680c4cfcb 296
Bobty 18:5de680c4cfcb 297 // Handle request for files/listing from SDCard
Bobty 17:080f2bed8b36 298 bool RdWebServer::handleSDFileRequest(char* inFileName, char* argStr, TCPSocketConnection &clientSocketConn)
Bobty 17:080f2bed8b36 299 {
Bobty 17:080f2bed8b36 300 bool handledOk = false;
Bobty 6:46285c519af2 301 const int HTTPD_MAX_FNAME_LENGTH = 127;
Bobty 6:46285c519af2 302 char filename[HTTPD_MAX_FNAME_LENGTH+1];
Bobty 6:46285c519af2 303
Bobty 19:f67ac231b570 304 RD_INFO("Requesting file %s", inFileName);
Bobty 6:46285c519af2 305
Bobty 12:c14ffd4ec125 306 #ifdef SUPPORT_FOLDER_VIEW
Bobty 10:b4b9d4d5e5be 307 if ((strlen(inFileName) > 0) && (inFileName[strlen(inFileName)-1] == '/'))
Bobty 6:46285c519af2 308 {
Bobty 19:f67ac231b570 309 RD_INFO("Request directory %s%s", _pBaseWebFolder, inFileName);
Bobty 6:46285c519af2 310 sprintf(filename, "%s%s", _pBaseWebFolder, inFileName);
Bobty 26:3c4c10e989b1 311
Bobty 26:3c4c10e989b1 312 // Obtain lock on SD card (if reqd)
Bobty 26:3c4c10e989b1 313 if (_pSdCardMutex)
Bobty 26:3c4c10e989b1 314 _pSdCardMutex->lock();
Bobty 26:3c4c10e989b1 315
Bobty 6:46285c519af2 316 DIR *d = opendir(filename);
Bobty 11:cec51b430b20 317 if (d != NULL)
Bobty 11:cec51b430b20 318 {
Bobty 17:080f2bed8b36 319 formHTTPHeader("200 OK", "text/html", -1);
Bobty 23:0fc3d7b5e596 320 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 17:080f2bed8b36 321 sprintf(_httpHeader,"<html><head><title>Directory Listing</title></head><body><h1>%s</h1><ul>", inFileName);
Bobty 23:0fc3d7b5e596 322 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 6:46285c519af2 323 struct dirent *p;
Bobty 11:cec51b430b20 324 while((p = readdir(d)) != NULL)
Bobty 11:cec51b430b20 325 {
Bobty 19:f67ac231b570 326 RD_INFO("%s", p->d_name);
Bobty 17:080f2bed8b36 327 sprintf(_httpHeader,"<li>%s</li>", p->d_name);
Bobty 23:0fc3d7b5e596 328 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 6:46285c519af2 329 }
Bobty 6:46285c519af2 330 }
Bobty 6:46285c519af2 331 closedir(d);
Bobty 26:3c4c10e989b1 332
Bobty 26:3c4c10e989b1 333 // Release lock on SD card (if reqd)
Bobty 26:3c4c10e989b1 334 if (_pSdCardMutex)
Bobty 26:3c4c10e989b1 335 _pSdCardMutex->unlock();
Bobty 26:3c4c10e989b1 336
Bobty 11:cec51b430b20 337 RD_DBG("Directory closed\n");
Bobty 17:080f2bed8b36 338 sprintf(_httpHeader,"</ul></body></html>");
Bobty 23:0fc3d7b5e596 339 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 17:080f2bed8b36 340 handledOk = true;
Bobty 6:46285c519af2 341 }
Bobty 6:46285c519af2 342 else
Bobty 12:c14ffd4ec125 343 #endif
Bobty 6:46285c519af2 344 {
Bobty 6:46285c519af2 345 sprintf(filename, "%s%s", _pBaseWebFolder, inFileName);
Bobty 19:f67ac231b570 346 RD_INFO("Filename %s", filename);
Bobty 6:46285c519af2 347
Bobty 26:3c4c10e989b1 348 // Obtain lock on SD card (if reqd)
Bobty 26:3c4c10e989b1 349 if (_pSdCardMutex)
Bobty 26:3c4c10e989b1 350 _pSdCardMutex->lock();
Bobty 26:3c4c10e989b1 351
Bobty 6:46285c519af2 352 FILE* fp = fopen(filename, "r");
Bobty 6:46285c519af2 353 if (fp == NULL)
Bobty 6:46285c519af2 354 {
Bobty 19:f67ac231b570 355 RD_WARN("Filename %s not found", filename);
Bobty 17:080f2bed8b36 356 formHTTPHeader("404 Not Found", "text/plain", 0);
Bobty 23:0fc3d7b5e596 357 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 17:080f2bed8b36 358 handledOk = true;
Bobty 6:46285c519af2 359 }
Bobty 6:46285c519af2 360 else
Bobty 6:46285c519af2 361 {
Bobty 19:f67ac231b570 362 RD_INFO("Sending file %s", filename);
Bobty 17:080f2bed8b36 363 // Find file length
Bobty 14:4b83670854f0 364 fseek(fp, 0L, SEEK_END);
Bobty 14:4b83670854f0 365 int sz = ftell(fp);
Bobty 14:4b83670854f0 366 fseek(fp, 0L, SEEK_SET);
Bobty 17:080f2bed8b36 367 // Get mime type
Bobty 17:080f2bed8b36 368 char* mimeType = getMimeTypeStr(filename);
Bobty 18:5de680c4cfcb 369 RD_DBG("MIME TYPE %s", mimeType);
Bobty 17:080f2bed8b36 370 // Form header
Bobty 17:080f2bed8b36 371 formHTTPHeader("200 OK", mimeType, sz);
Bobty 23:0fc3d7b5e596 372 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 14:4b83670854f0 373 // Read file in blocks and send
Bobty 6:46285c519af2 374 int rdCnt = 0;
Bobty 6:46285c519af2 375 char fileBuf[1024];
Bobty 6:46285c519af2 376 while ((rdCnt = fread(fileBuf, sizeof( char ), 1024, fp)) == 1024)
Bobty 6:46285c519af2 377 {
Bobty 23:0fc3d7b5e596 378 clientSocketConn.send_all(fileBuf, rdCnt);
Bobty 6:46285c519af2 379 }
Bobty 23:0fc3d7b5e596 380 clientSocketConn.send_all(fileBuf, rdCnt);
Bobty 6:46285c519af2 381 fclose(fp);
Bobty 17:080f2bed8b36 382 handledOk = true;
Bobty 6:46285c519af2 383 }
Bobty 26:3c4c10e989b1 384
Bobty 26:3c4c10e989b1 385 // Obtain lock on SD card (if reqd)
Bobty 26:3c4c10e989b1 386 if (_pSdCardMutex)
Bobty 26:3c4c10e989b1 387 _pSdCardMutex->unlock();
Bobty 26:3c4c10e989b1 388
Bobty 6:46285c519af2 389 }
Bobty 17:080f2bed8b36 390 return handledOk;
Bobty 6:46285c519af2 391 }
Bobty 6:46285c519af2 392
Bobty 18:5de680c4cfcb 393 // Send a file from cache - used for local files only
Bobty 15:0865fa4b046a 394 #ifdef SUPPORT_LOCAL_FILE_CACHE
Bobty 17:080f2bed8b36 395 void RdWebServer::sendFromCache(RdFileCacheEntry* pCacheEntry, TCPSocketConnection &clientSocketConn)
Bobty 6:46285c519af2 396 {
Bobty 19:f67ac231b570 397 RD_INFO("Sending file %s from cache %d bytes", pCacheEntry->_fileName, pCacheEntry->_nFileLen);
Bobty 17:080f2bed8b36 398 // Get mime type
Bobty 17:080f2bed8b36 399 char* mimeType = getMimeTypeStr(pCacheEntry->_fileName);
Bobty 17:080f2bed8b36 400 RD_INFO("MIME TYPE %s", mimeType);
Bobty 17:080f2bed8b36 401 // Form header
Bobty 17:080f2bed8b36 402 formHTTPHeader("200 OK", mimeType, pCacheEntry->_nFileLen);
Bobty 23:0fc3d7b5e596 403 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 6:46285c519af2 404 char* pMem = pCacheEntry->_pFileContent;
Bobty 6:46285c519af2 405 int nLenLeft = pCacheEntry->_nFileLen;
Bobty 6:46285c519af2 406 int blkSize = 2048;
Bobty 6:46285c519af2 407 while(nLenLeft > 0)
Bobty 6:46285c519af2 408 {
Bobty 6:46285c519af2 409 if (blkSize > nLenLeft)
Bobty 6:46285c519af2 410 blkSize = nLenLeft;
Bobty 23:0fc3d7b5e596 411 clientSocketConn.send_all(pMem, blkSize);
Bobty 6:46285c519af2 412 pMem += blkSize;
Bobty 6:46285c519af2 413 nLenLeft -= blkSize;
Bobty 6:46285c519af2 414 }
Bobty 6:46285c519af2 415 }
Bobty 15:0865fa4b046a 416 #endif
Bobty 6:46285c519af2 417
Bobty 18:5de680c4cfcb 418 // Handle a request for a local file
Bobty 17:080f2bed8b36 419 bool RdWebServer::handleLocalFileRequest(char* inFileName, char* argStr, TCPSocketConnection &clientSocketConn, bool bCacheIfPossible)
Bobty 6:46285c519af2 420 {
Bobty 12:c14ffd4ec125 421
Bobty 12:c14ffd4ec125 422 #ifdef SUPPORT_LOCAL_FILESYSTEM
Bobty 12:c14ffd4ec125 423
Bobty 6:46285c519af2 424 const int HTTPD_MAX_FNAME_LENGTH = 127;
Bobty 6:46285c519af2 425 char localFilename[HTTPD_MAX_FNAME_LENGTH+1];
Bobty 6:46285c519af2 426 char reqFileNameStr[HTTPD_MAX_FNAME_LENGTH+1];
Bobty 6:46285c519af2 427
Bobty 19:f67ac231b570 428 RD_INFO("Requesting local file %s", inFileName);
Bobty 6:46285c519af2 429 sprintf(reqFileNameStr, "/%s", inFileName);
Bobty 6:46285c519af2 430 sprintf(localFilename, "/local/%s", inFileName);
Bobty 6:46285c519af2 431
Bobty 6:46285c519af2 432 if (bCacheIfPossible)
Bobty 6:46285c519af2 433 {
Bobty 6:46285c519af2 434 // Check if file already cached
Bobty 6:46285c519af2 435 bool bTryToCache = true;
Bobty 6:46285c519af2 436 for (std::vector<RdFileCacheEntry*>::iterator it = _cachedFiles.begin() ; it != _cachedFiles.end(); ++it)
Bobty 6:46285c519af2 437 {
Bobty 6:46285c519af2 438 if (strcmp(inFileName, (*it)->_fileName) == 0)
Bobty 6:46285c519af2 439 {
Bobty 6:46285c519af2 440 if ((*it)->_bCacheValid)
Bobty 6:46285c519af2 441 {
Bobty 21:2dfb56648b93 442 sendFromCache(*it, clientSocketConn);
Bobty 17:080f2bed8b36 443 return true;
Bobty 6:46285c519af2 444 }
Bobty 6:46285c519af2 445 bTryToCache = false; // don't try to cache as cacheing must have already failed
Bobty 6:46285c519af2 446 }
Bobty 6:46285c519af2 447 }
Bobty 6:46285c519af2 448
Bobty 6:46285c519af2 449 // See if we can cache the file
Bobty 6:46285c519af2 450 if (bTryToCache)
Bobty 6:46285c519af2 451 {
Bobty 6:46285c519af2 452 RdFileCacheEntry* pCacheEntry = new RdFileCacheEntry(inFileName);
Bobty 6:46285c519af2 453 if (pCacheEntry)
Bobty 6:46285c519af2 454 {
Bobty 6:46285c519af2 455 bool bCacheSuccess = pCacheEntry->readLocalFileIntoCache(localFilename);
Bobty 6:46285c519af2 456 // Store the cache entry even if reading failed (mem alloc or file not found, etc) so we don't try to cache again
Bobty 6:46285c519af2 457 _cachedFiles.push_back(pCacheEntry);
Bobty 6:46285c519af2 458 if (bCacheSuccess)
Bobty 6:46285c519af2 459 {
Bobty 21:2dfb56648b93 460 sendFromCache(pCacheEntry, clientSocketConn);
Bobty 17:080f2bed8b36 461 return true;
Bobty 6:46285c519af2 462 }
Bobty 6:46285c519af2 463 }
Bobty 6:46285c519af2 464 }
Bobty 6:46285c519af2 465 }
Bobty 6:46285c519af2 466
Bobty 6:46285c519af2 467 LocalFileSystem local("local");
Bobty 6:46285c519af2 468
Bobty 6:46285c519af2 469 FILE* fp = fopen(localFilename, "r");
Bobty 6:46285c519af2 470 if (fp == NULL)
Bobty 6:46285c519af2 471 {
Bobty 19:f67ac231b570 472 RD_WARN("Local file %s not found", localFilename);
Bobty 17:080f2bed8b36 473 formHTTPHeader("404 Not Found", "text/plain", 0);
Bobty 23:0fc3d7b5e596 474 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 17:080f2bed8b36 475 return true;
Bobty 6:46285c519af2 476 }
Bobty 6:46285c519af2 477 else
Bobty 6:46285c519af2 478 {
Bobty 19:f67ac231b570 479 RD_INFO("Sending file %s from disk", localFilename);
Bobty 17:080f2bed8b36 480 // Find file length
Bobty 17:080f2bed8b36 481 fseek(fp, 0L, SEEK_END);
Bobty 17:080f2bed8b36 482 int sz = ftell(fp);
Bobty 17:080f2bed8b36 483 fseek(fp, 0L, SEEK_SET);
Bobty 17:080f2bed8b36 484 // Get mime type
Bobty 17:080f2bed8b36 485 char* mimeType = getMimeTypeStr(localFilename);
Bobty 18:5de680c4cfcb 486 RD_DBG("MIME TYPE %s", mimeType);
Bobty 17:080f2bed8b36 487 // Form header
Bobty 17:080f2bed8b36 488 formHTTPHeader("200 OK", mimeType, sz);
Bobty 23:0fc3d7b5e596 489 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 6:46285c519af2 490 int rdCnt = 0;
Bobty 17:080f2bed8b36 491 while ((rdCnt = fread(_httpHeader, sizeof( char ), sizeof(_httpHeader), fp)) == sizeof(_httpHeader))
Bobty 6:46285c519af2 492 {
Bobty 23:0fc3d7b5e596 493 clientSocketConn.send_all(_httpHeader, rdCnt);
Bobty 6:46285c519af2 494 }
Bobty 17:080f2bed8b36 495 if (rdCnt != 0)
Bobty 23:0fc3d7b5e596 496 clientSocketConn.send_all(_httpHeader, rdCnt);
Bobty 6:46285c519af2 497 fclose(fp);
Bobty 17:080f2bed8b36 498 return true;
Bobty 6:46285c519af2 499 }
Bobty 12:c14ffd4ec125 500
Bobty 12:c14ffd4ec125 501 #else
Bobty 12:c14ffd4ec125 502
Bobty 19:f67ac231b570 503 RD_WARN("Local file system not supported");
Bobty 17:080f2bed8b36 504 formHTTPHeader("404 Not Found", "text/plain", 0);
Bobty 23:0fc3d7b5e596 505 clientSocketConn.send_all(_httpHeader,strlen(_httpHeader));
Bobty 17:080f2bed8b36 506 return true;
Bobty 12:c14ffd4ec125 507
Bobty 12:c14ffd4ec125 508 #endif
Bobty 6:46285c519af2 509 }
Bobty 6:46285c519af2 510
Bobty 18:5de680c4cfcb 511 // Read file into cache
Bobty 15:0865fa4b046a 512 #ifdef SUPPORT_LOCAL_FILE_CACHE
Bobty 6:46285c519af2 513 bool RdFileCacheEntry::readLocalFileIntoCache(char* fileName)
Bobty 6:46285c519af2 514 {
Bobty 12:c14ffd4ec125 515 #ifdef SUPPORT_LOCAL_FILESYSTEM
Bobty 12:c14ffd4ec125 516
Bobty 19:f67ac231b570 517 RD_INFO("Reading into cache %s", fileName);
Bobty 6:46285c519af2 518 LocalFileSystem local("local");
Bobty 6:46285c519af2 519 FILE* fp = fopen(fileName, "r");
Bobty 6:46285c519af2 520 if (fp == NULL)
Bobty 6:46285c519af2 521 {
Bobty 19:f67ac231b570 522 RD_WARN("Failed to open file");
Bobty 6:46285c519af2 523 return false;
Bobty 6:46285c519af2 524 }
Bobty 21:2dfb56648b93 525 RD_DBG("Seeking ");
Bobty 6:46285c519af2 526 fseek(fp, 0, SEEK_END);
Bobty 6:46285c519af2 527 _nFileLen = (int)ftell(fp);
Bobty 21:2dfb56648b93 528 RD_DBG("Len %d ", _nFileLen);
Bobty 6:46285c519af2 529 _pFileContent = new char[_nFileLen];
Bobty 21:2dfb56648b93 530 RD_DBG("Buf %08x ", _pFileContent);
Bobty 6:46285c519af2 531 if (!_pFileContent)
Bobty 6:46285c519af2 532 {
Bobty 19:f67ac231b570 533 RD_WARN("Failed to allocate %lu", _nFileLen);
Bobty 6:46285c519af2 534 fclose(fp);
Bobty 6:46285c519af2 535 return false;
Bobty 6:46285c519af2 536 }
Bobty 19:f67ac231b570 537 RD_DBG("Allocated");
Bobty 6:46285c519af2 538 memset(_pFileContent, 0, _nFileLen);
Bobty 6:46285c519af2 539 fseek(fp, 0, SEEK_SET);
Bobty 6:46285c519af2 540 char* pMem = _pFileContent;
Bobty 6:46285c519af2 541 char fileBuf[100];
Bobty 6:46285c519af2 542 int totCnt = 0;
Bobty 6:46285c519af2 543 int rdCnt = 0;
Bobty 19:f67ac231b570 544 RD_DBG("Reading");
Bobty 6:46285c519af2 545 while (true)
Bobty 6:46285c519af2 546 {
Bobty 6:46285c519af2 547 int toRead = _nFileLen - totCnt;
Bobty 6:46285c519af2 548 if (toRead > sizeof(fileBuf))
Bobty 6:46285c519af2 549 toRead = sizeof(fileBuf);
Bobty 6:46285c519af2 550 if (toRead <= 0)
Bobty 6:46285c519af2 551 break;
Bobty 6:46285c519af2 552 rdCnt = fread(fileBuf, sizeof(char), toRead, fp);
Bobty 6:46285c519af2 553 if (rdCnt <= 0)
Bobty 6:46285c519af2 554 break;
Bobty 19:f67ac231b570 555 RD_DBG("Read %d tot %d of %d", rdCnt, totCnt, _nFileLen);
Bobty 6:46285c519af2 556 memcpy(pMem, fileBuf, rdCnt);
Bobty 6:46285c519af2 557 pMem += rdCnt;
Bobty 6:46285c519af2 558 totCnt += rdCnt;
Bobty 6:46285c519af2 559 }
Bobty 19:f67ac231b570 560 RD_DBG("Done read");
Bobty 6:46285c519af2 561 fclose(fp);
Bobty 19:f67ac231b570 562 RD_DBG("Success in caching %d bytes (read %d)", _nFileLen, totCnt);
Bobty 6:46285c519af2 563 _bCacheValid = true;
Bobty 0:b5b4d07f7827 564 return true;
Bobty 12:c14ffd4ec125 565 #else
Bobty 12:c14ffd4ec125 566 return false;
Bobty 12:c14ffd4ec125 567 #endif
Bobty 0:b5b4d07f7827 568 }
Bobty 0:b5b4d07f7827 569
Bobty 15:0865fa4b046a 570 #endif
Bobty 15:0865fa4b046a 571
Bobty 18:5de680c4cfcb 572 // Extract arguments from command
Bobty 24:27800de38eab 573 bool RdWebServer::extractCmdArgs(char* buf, char* pCmdStr, int maxCmdStrLen, char* pArgStr, int maxArgStrLen, int& contentLen)
Bobty 1:75bb184de749 574 {
Bobty 24:27800de38eab 575 contentLen = -1;
Bobty 1:75bb184de749 576 *pCmdStr = '\0';
Bobty 1:75bb184de749 577 *pArgStr = '\0';
Bobty 1:75bb184de749 578 int cmdStrLen = 0;
Bobty 1:75bb184de749 579 int argStrLen = 0;
Bobty 1:75bb184de749 580 if (buf == NULL)
Bobty 1:75bb184de749 581 return false;
Bobty 24:27800de38eab 582 // Check for Content-length header
Bobty 24:27800de38eab 583 char* contentLenText = "Content-Length:";
Bobty 24:27800de38eab 584 char* pContLen = strstr(buf, contentLenText);
Bobty 24:27800de38eab 585 if (pContLen)
Bobty 24:27800de38eab 586 {
Bobty 24:27800de38eab 587 if (*(pContLen + strlen(contentLenText)) != '\0')
Bobty 24:27800de38eab 588 contentLen = atoi(pContLen + strlen(contentLenText));
Bobty 24:27800de38eab 589 }
Bobty 24:27800de38eab 590
Bobty 7:fe7c33f7fbb8 591 // Check for first slash
Bobty 1:75bb184de749 592 char* pSlash1 = strchr(buf, '/');
Bobty 1:75bb184de749 593 if (pSlash1 == NULL)
Bobty 1:75bb184de749 594 return false;
Bobty 1:75bb184de749 595 pSlash1++;
Bobty 7:fe7c33f7fbb8 596 // Extract command
Bobty 1:75bb184de749 597 while(*pSlash1)
Bobty 1:75bb184de749 598 {
Bobty 1:75bb184de749 599 if (cmdStrLen >= maxCmdStrLen-1)
Bobty 1:75bb184de749 600 break;
Bobty 7:fe7c33f7fbb8 601 if ((*pSlash1 == '/') || (*pSlash1 == ' ') || (*pSlash1 == '\n') || (*pSlash1 == '?') || (*pSlash1 == '&'))
Bobty 1:75bb184de749 602 break;
Bobty 1:75bb184de749 603 *pCmdStr++ = *pSlash1++;
Bobty 1:75bb184de749 604 *pCmdStr = '\0';
Bobty 1:75bb184de749 605 cmdStrLen++;
Bobty 1:75bb184de749 606 }
Bobty 1:75bb184de749 607 if ((*pSlash1 == '\0') || (*pSlash1 == ' ') || (*pSlash1 == '\n'))
Bobty 1:75bb184de749 608 return true;
Bobty 7:fe7c33f7fbb8 609 // Now args
Bobty 1:75bb184de749 610 *pSlash1++;
Bobty 1:75bb184de749 611 while(*pSlash1)
Bobty 1:75bb184de749 612 {
Bobty 1:75bb184de749 613 if (argStrLen >= maxArgStrLen-1)
Bobty 1:75bb184de749 614 break;
Bobty 1:75bb184de749 615 if ((*pSlash1 == ' ') || (*pSlash1 == '\n'))
Bobty 1:75bb184de749 616 break;
Bobty 1:75bb184de749 617 *pArgStr++ = *pSlash1++;
Bobty 1:75bb184de749 618 *pArgStr = '\0';
Bobty 1:75bb184de749 619 argStrLen++;
Bobty 1:75bb184de749 620 }
Bobty 1:75bb184de749 621 return true;
Bobty 1:75bb184de749 622 }
Bobty 19:f67ac231b570 623
Bobty 24:27800de38eab 624 unsigned char* RdWebServer::getPayloadDataFromMsg(char* msgBuf, int msgLen, int& payloadLen)
Bobty 19:f67ac231b570 625 {
Bobty 24:27800de38eab 626 payloadLen = -1;
Bobty 19:f67ac231b570 627 char* ptr = strstr(msgBuf, "\r\n\r\n");
Bobty 19:f67ac231b570 628 if (ptr)
Bobty 24:27800de38eab 629 {
Bobty 24:27800de38eab 630 payloadLen = msgLen - (ptr+4-msgBuf);
Bobty 21:2dfb56648b93 631 return (unsigned char*) (ptr+4);
Bobty 24:27800de38eab 632 }
Bobty 24:27800de38eab 633 return NULL;
Bobty 19:f67ac231b570 634 }
Bobty 21:2dfb56648b93 635
Bobty 24:27800de38eab 636 int RdWebServer::getContentLengthFromMsg(char* msgBuf)
Bobty 21:2dfb56648b93 637 {
Bobty 21:2dfb56648b93 638 char* ptr = strstr(msgBuf, "Content-Length:");
Bobty 21:2dfb56648b93 639 if (ptr)
Bobty 21:2dfb56648b93 640 {
Bobty 21:2dfb56648b93 641 ptr += 15;
Bobty 21:2dfb56648b93 642 int contentLen = atoi(ptr);
Bobty 21:2dfb56648b93 643 if (contentLen >= 0)
Bobty 21:2dfb56648b93 644 return contentLen;
Bobty 21:2dfb56648b93 645 }
Bobty 21:2dfb56648b93 646 return 0;
Bobty 21:2dfb56648b93 647 }