First step: AutoIP compiled in and working

Dependencies:   mbed

Committer:
darran
Date:
Fri Jun 18 15:54:21 2010 +0000
Revision:
1:4218cacaf696
Parent:
0:55a05330f8cc

        

Who changed what in which revision?

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