This version has the index file and data pages on a SD card (512Mbyte) it does not suffer from the autorun problem when directly writtin to the mbed flash memory It makes readings from one solar panel for open and loaded voltages every 'interval' seconds Every readingsPerPage a new web page is created and indexed on a readings web page Activty is shown by the flashing blue led (0.5s) means it is connected and output via the serial over usb port. Data is preserved on subsequent power ups by incrementing file number. PMR 15/9/10 */

Dependencies:   EthernetNetIf NTPClient_NetServices mbed SDFileSystem

Committer:
pmr1
Date:
Sat Sep 18 13:31:41 2010 +0000
Revision:
0:d6b2d5c4c48f

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pmr1 0:d6b2d5c4c48f 1
pmr1 0:d6b2d5c4c48f 2 /*
pmr1 0:d6b2d5c4c48f 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
pmr1 0:d6b2d5c4c48f 4
pmr1 0:d6b2d5c4c48f 5 Permission is hereby granted, free of charge, to any person obtaining a copy
pmr1 0:d6b2d5c4c48f 6 of this software and associated documentation files (the "Software"), to deal
pmr1 0:d6b2d5c4c48f 7 in the Software without restriction, including without limitation the rights
pmr1 0:d6b2d5c4c48f 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
pmr1 0:d6b2d5c4c48f 9 copies of the Software, and to permit persons to whom the Software is
pmr1 0:d6b2d5c4c48f 10 furnished to do so, subject to the following conditions:
pmr1 0:d6b2d5c4c48f 11
pmr1 0:d6b2d5c4c48f 12 The above copyright notice and this permission notice shall be included in
pmr1 0:d6b2d5c4c48f 13 all copies or substantial portions of the Software.
pmr1 0:d6b2d5c4c48f 14
pmr1 0:d6b2d5c4c48f 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
pmr1 0:d6b2d5c4c48f 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
pmr1 0:d6b2d5c4c48f 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
pmr1 0:d6b2d5c4c48f 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
pmr1 0:d6b2d5c4c48f 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
pmr1 0:d6b2d5c4c48f 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
pmr1 0:d6b2d5c4c48f 21 THE SOFTWARE.
pmr1 0:d6b2d5c4c48f 22 */
pmr1 0:d6b2d5c4c48f 23
pmr1 0:d6b2d5c4c48f 24 #include "core/netservice.h"
pmr1 0:d6b2d5c4c48f 25 #include "HTTPRequestDispatcher.h"
pmr1 0:d6b2d5c4c48f 26 #include "HTTPRequestHandler.h"
pmr1 0:d6b2d5c4c48f 27 #include <string.h>
pmr1 0:d6b2d5c4c48f 28
pmr1 0:d6b2d5c4c48f 29 //#define __DEBUG
pmr1 0:d6b2d5c4c48f 30 #include "dbg/dbg.h"
pmr1 0:d6b2d5c4c48f 31
pmr1 0:d6b2d5c4c48f 32 HTTPRequestDispatcher::HTTPRequestDispatcher(HTTPServer* pSvr, TCPSocket* pTCPSocket) : NetService(), m_pSvr(pSvr), m_pTCPSocket(pTCPSocket), m_watchdog(), m_closed(false)
pmr1 0:d6b2d5c4c48f 33 {
pmr1 0:d6b2d5c4c48f 34 m_pTCPSocket->setOnEvent(this, &HTTPRequestDispatcher::onTCPSocketEvent);
pmr1 0:d6b2d5c4c48f 35 m_watchdog.attach_us<HTTPRequestDispatcher>(this, &HTTPRequestDispatcher::onTimeout, HTTP_REQUEST_TIMEOUT * 1000);
pmr1 0:d6b2d5c4c48f 36 }
pmr1 0:d6b2d5c4c48f 37
pmr1 0:d6b2d5c4c48f 38 HTTPRequestDispatcher::~HTTPRequestDispatcher()
pmr1 0:d6b2d5c4c48f 39 {
pmr1 0:d6b2d5c4c48f 40 close();
pmr1 0:d6b2d5c4c48f 41 }
pmr1 0:d6b2d5c4c48f 42
pmr1 0:d6b2d5c4c48f 43 void HTTPRequestDispatcher::dispatchRequest()
pmr1 0:d6b2d5c4c48f 44 {
pmr1 0:d6b2d5c4c48f 45 string path;
pmr1 0:d6b2d5c4c48f 46 string meth;
pmr1 0:d6b2d5c4c48f 47 HTTP_METH methCode;
pmr1 0:d6b2d5c4c48f 48
pmr1 0:d6b2d5c4c48f 49 DBG("Dispatching req\r\n");
pmr1 0:d6b2d5c4c48f 50
pmr1 0:d6b2d5c4c48f 51 if( !getRequest(&path, &meth ) )
pmr1 0:d6b2d5c4c48f 52 {
pmr1 0:d6b2d5c4c48f 53 close();
pmr1 0:d6b2d5c4c48f 54 return; //Invalid request
pmr1 0:d6b2d5c4c48f 55 }
pmr1 0:d6b2d5c4c48f 56
pmr1 0:d6b2d5c4c48f 57 if( !meth.compare("GET") )
pmr1 0:d6b2d5c4c48f 58 {
pmr1 0:d6b2d5c4c48f 59 methCode = HTTP_GET;
pmr1 0:d6b2d5c4c48f 60 }
pmr1 0:d6b2d5c4c48f 61 else if( !meth.compare("POST") )
pmr1 0:d6b2d5c4c48f 62 {
pmr1 0:d6b2d5c4c48f 63 methCode = HTTP_POST;
pmr1 0:d6b2d5c4c48f 64 }
pmr1 0:d6b2d5c4c48f 65 else if( !meth.compare("HEAD") )
pmr1 0:d6b2d5c4c48f 66 {
pmr1 0:d6b2d5c4c48f 67 methCode = HTTP_HEAD;
pmr1 0:d6b2d5c4c48f 68 }
pmr1 0:d6b2d5c4c48f 69 else
pmr1 0:d6b2d5c4c48f 70 {
pmr1 0:d6b2d5c4c48f 71 close(); //Parse error
pmr1 0:d6b2d5c4c48f 72 return;
pmr1 0:d6b2d5c4c48f 73 }
pmr1 0:d6b2d5c4c48f 74
pmr1 0:d6b2d5c4c48f 75 DBG("Looking for a handler\r\n");
pmr1 0:d6b2d5c4c48f 76
pmr1 0:d6b2d5c4c48f 77 map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*) >::iterator it;
pmr1 0:d6b2d5c4c48f 78 // it = m_pSvr->m_lpHandlers.find(rootPath); //We are friends so we can do that
pmr1 0:d6b2d5c4c48f 79 // NEW CODE START:
pmr1 0:d6b2d5c4c48f 80 int root_len = 0;
pmr1 0:d6b2d5c4c48f 81 for (it = m_pSvr->m_lpHandlers.begin(); it != m_pSvr->m_lpHandlers.end(); it++)
pmr1 0:d6b2d5c4c48f 82 {
pmr1 0:d6b2d5c4c48f 83 DBG("Checking %s...\n", (*it).first.c_str());
pmr1 0:d6b2d5c4c48f 84 root_len = (*it).first.length();
pmr1 0:d6b2d5c4c48f 85 if ( root_len &&
pmr1 0:d6b2d5c4c48f 86 !path.compare( 0, root_len, (*it).first ) &&
pmr1 0:d6b2d5c4c48f 87 (path[root_len] == '/' || path[root_len] == '\0'))
pmr1 0:d6b2d5c4c48f 88 {
pmr1 0:d6b2d5c4c48f 89 DBG("Found (%s)\n", (*it).first.c_str());
pmr1 0:d6b2d5c4c48f 90 // Found!
pmr1 0:d6b2d5c4c48f 91 break; // for
pmr1 0:d6b2d5c4c48f 92 }
pmr1 0:d6b2d5c4c48f 93 }
pmr1 0:d6b2d5c4c48f 94 // NEW CODE END
pmr1 0:d6b2d5c4c48f 95 if((it == m_pSvr->m_lpHandlers.end()) && !(m_pSvr->m_lpHandlers.empty()))
pmr1 0:d6b2d5c4c48f 96 {
pmr1 0:d6b2d5c4c48f 97 DBG("Using default handler\n");
pmr1 0:d6b2d5c4c48f 98 it = m_pSvr->m_lpHandlers.end();
pmr1 0:d6b2d5c4c48f 99 it--; //Get the last element
pmr1 0:d6b2d5c4c48f 100 if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler
pmr1 0:d6b2d5c4c48f 101 it = m_pSvr->m_lpHandlers.end();
pmr1 0:d6b2d5c4c48f 102 root_len = 0;
pmr1 0:d6b2d5c4c48f 103 }
pmr1 0:d6b2d5c4c48f 104 if(it == m_pSvr->m_lpHandlers.end())
pmr1 0:d6b2d5c4c48f 105 {
pmr1 0:d6b2d5c4c48f 106 DBG("No handler found\n");
pmr1 0:d6b2d5c4c48f 107 close(); //No handler found
pmr1 0:d6b2d5c4c48f 108 return;
pmr1 0:d6b2d5c4c48f 109 }
pmr1 0:d6b2d5c4c48f 110
pmr1 0:d6b2d5c4c48f 111 DBG("Handler found.\r\n");
pmr1 0:d6b2d5c4c48f 112
pmr1 0:d6b2d5c4c48f 113 //HTTPRequestHandler* pHdlr = (*it).second(rootPath.c_str(), subPath.c_str(), m_pTCPSocket);
pmr1 0:d6b2d5c4c48f 114 //NEW CODE 1 LINE:
pmr1 0:d6b2d5c4c48f 115 HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, m_pTCPSocket);
pmr1 0:d6b2d5c4c48f 116 m_pTCPSocket = NULL; //We don't own it anymore
pmr1 0:d6b2d5c4c48f 117
pmr1 0:d6b2d5c4c48f 118 switch(methCode)
pmr1 0:d6b2d5c4c48f 119 {
pmr1 0:d6b2d5c4c48f 120 case HTTP_GET:
pmr1 0:d6b2d5c4c48f 121 pHdlr->doGet();
pmr1 0:d6b2d5c4c48f 122 break;
pmr1 0:d6b2d5c4c48f 123 case HTTP_POST:
pmr1 0:d6b2d5c4c48f 124 pHdlr->doPost();
pmr1 0:d6b2d5c4c48f 125 break;
pmr1 0:d6b2d5c4c48f 126 case HTTP_HEAD:
pmr1 0:d6b2d5c4c48f 127 pHdlr->doHead();
pmr1 0:d6b2d5c4c48f 128 break;
pmr1 0:d6b2d5c4c48f 129 }
pmr1 0:d6b2d5c4c48f 130
pmr1 0:d6b2d5c4c48f 131 DBG("Req handled (or being handled)\r\n");
pmr1 0:d6b2d5c4c48f 132 close();
pmr1 0:d6b2d5c4c48f 133 }
pmr1 0:d6b2d5c4c48f 134
pmr1 0:d6b2d5c4c48f 135 void HTTPRequestDispatcher::close() //Close socket and destroy data
pmr1 0:d6b2d5c4c48f 136 {
pmr1 0:d6b2d5c4c48f 137 if(m_closed)
pmr1 0:d6b2d5c4c48f 138 return;
pmr1 0:d6b2d5c4c48f 139 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
pmr1 0:d6b2d5c4c48f 140 m_watchdog.detach();
pmr1 0:d6b2d5c4c48f 141 if(m_pTCPSocket) //m_pTCPSocket Should only be destroyed if ownership not passed to an handler
pmr1 0:d6b2d5c4c48f 142 {
pmr1 0:d6b2d5c4c48f 143 m_pTCPSocket->resetOnEvent();
pmr1 0:d6b2d5c4c48f 144 m_pTCPSocket->close();
pmr1 0:d6b2d5c4c48f 145 delete m_pTCPSocket; //This fn might have been called by this socket (through an event), so DO NOT DESTROY IT HERE
pmr1 0:d6b2d5c4c48f 146 }
pmr1 0:d6b2d5c4c48f 147 NetService::close();
pmr1 0:d6b2d5c4c48f 148 }
pmr1 0:d6b2d5c4c48f 149
pmr1 0:d6b2d5c4c48f 150
pmr1 0:d6b2d5c4c48f 151 void HTTPRequestDispatcher::onTimeout() //Connection has timed out
pmr1 0:d6b2d5c4c48f 152 {
pmr1 0:d6b2d5c4c48f 153 close();
pmr1 0:d6b2d5c4c48f 154 }
pmr1 0:d6b2d5c4c48f 155
pmr1 0:d6b2d5c4c48f 156 bool HTTPRequestDispatcher::getRequest(string* path, string* meth)
pmr1 0:d6b2d5c4c48f 157 {
pmr1 0:d6b2d5c4c48f 158 char req[128];
pmr1 0:d6b2d5c4c48f 159 char c_path[128];
pmr1 0:d6b2d5c4c48f 160 char c_meth[128];
pmr1 0:d6b2d5c4c48f 161 const int maxLen = 128;
pmr1 0:d6b2d5c4c48f 162 char* p = req;
pmr1 0:d6b2d5c4c48f 163 //Read Line
pmr1 0:d6b2d5c4c48f 164 int ret;
pmr1 0:d6b2d5c4c48f 165 int len = 0;
pmr1 0:d6b2d5c4c48f 166 for(int i = 0; i < maxLen - 1; i++)
pmr1 0:d6b2d5c4c48f 167 {
pmr1 0:d6b2d5c4c48f 168 ret = m_pTCPSocket->recv(p, 1);
pmr1 0:d6b2d5c4c48f 169 if(!ret)
pmr1 0:d6b2d5c4c48f 170 {
pmr1 0:d6b2d5c4c48f 171 break;
pmr1 0:d6b2d5c4c48f 172 }
pmr1 0:d6b2d5c4c48f 173 if( (len > 1) && *(p-1)=='\r' && *p=='\n' )
pmr1 0:d6b2d5c4c48f 174 {
pmr1 0:d6b2d5c4c48f 175 p--;
pmr1 0:d6b2d5c4c48f 176 len-=2;
pmr1 0:d6b2d5c4c48f 177 break;
pmr1 0:d6b2d5c4c48f 178 }
pmr1 0:d6b2d5c4c48f 179 else if( *p=='\n' )
pmr1 0:d6b2d5c4c48f 180 {
pmr1 0:d6b2d5c4c48f 181 len--;
pmr1 0:d6b2d5c4c48f 182 break;
pmr1 0:d6b2d5c4c48f 183 }
pmr1 0:d6b2d5c4c48f 184 p++;
pmr1 0:d6b2d5c4c48f 185 len++;
pmr1 0:d6b2d5c4c48f 186 }
pmr1 0:d6b2d5c4c48f 187 *p = 0;
pmr1 0:d6b2d5c4c48f 188
pmr1 0:d6b2d5c4c48f 189 DBG("Parsing request : %s\r\n", req);
pmr1 0:d6b2d5c4c48f 190
pmr1 0:d6b2d5c4c48f 191 ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path);
pmr1 0:d6b2d5c4c48f 192 if(ret !=2)
pmr1 0:d6b2d5c4c48f 193 return false;
pmr1 0:d6b2d5c4c48f 194
pmr1 0:d6b2d5c4c48f 195 *meth = string(c_meth);
pmr1 0:d6b2d5c4c48f 196 // NEW CODE (old code removed):
pmr1 0:d6b2d5c4c48f 197 *path = string(c_path);
pmr1 0:d6b2d5c4c48f 198 return true;
pmr1 0:d6b2d5c4c48f 199 }
pmr1 0:d6b2d5c4c48f 200
pmr1 0:d6b2d5c4c48f 201
pmr1 0:d6b2d5c4c48f 202
pmr1 0:d6b2d5c4c48f 203 void HTTPRequestDispatcher::onTCPSocketEvent(TCPSocketEvent e)
pmr1 0:d6b2d5c4c48f 204 {
pmr1 0:d6b2d5c4c48f 205
pmr1 0:d6b2d5c4c48f 206 DBG("\r\nEvent %d\r\n", e);
pmr1 0:d6b2d5c4c48f 207
pmr1 0:d6b2d5c4c48f 208 if(m_closed)
pmr1 0:d6b2d5c4c48f 209 {
pmr1 0:d6b2d5c4c48f 210 DBG("\r\nWARN: Discarded\r\n");
pmr1 0:d6b2d5c4c48f 211 return;
pmr1 0:d6b2d5c4c48f 212 }
pmr1 0:d6b2d5c4c48f 213
pmr1 0:d6b2d5c4c48f 214 switch(e)
pmr1 0:d6b2d5c4c48f 215 {
pmr1 0:d6b2d5c4c48f 216 case TCPSOCKET_READABLE:
pmr1 0:d6b2d5c4c48f 217 m_watchdog.detach();
pmr1 0:d6b2d5c4c48f 218 m_pTCPSocket->resetOnEvent();
pmr1 0:d6b2d5c4c48f 219 //Req arrived, dispatch :
pmr1 0:d6b2d5c4c48f 220 dispatchRequest();
pmr1 0:d6b2d5c4c48f 221 break;
pmr1 0:d6b2d5c4c48f 222 case TCPSOCKET_CONTIMEOUT:
pmr1 0:d6b2d5c4c48f 223 case TCPSOCKET_CONRST:
pmr1 0:d6b2d5c4c48f 224 case TCPSOCKET_CONABRT:
pmr1 0:d6b2d5c4c48f 225 case TCPSOCKET_ERROR:
pmr1 0:d6b2d5c4c48f 226 case TCPSOCKET_DISCONNECTED:
pmr1 0:d6b2d5c4c48f 227 close();
pmr1 0:d6b2d5c4c48f 228 break;
pmr1 0:d6b2d5c4c48f 229 }
pmr1 0:d6b2d5c4c48f 230
pmr1 0:d6b2d5c4c48f 231 }