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:
Mon Feb 08 14:08:42 2016 +0000
Revision:
29:46998f2e458f
Parent:
28:99036ff32459
Fixed RTOS namespace issue

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