Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
HTTPRequestDispatcher.cpp
00001 00002 /* 00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00021 THE SOFTWARE. 00022 */ 00023 00024 #include "HTTPRequestDispatcher.h" 00025 #include "HTTPRequestHandler.h" 00026 #include <string.h> 00027 00028 //#define __DEBUG 00029 #include "dbg/dbg.h" 00030 00031 HTTPRequestDispatcher::HTTPRequestDispatcher(HTTPServer* pSvr, TCPSocket* pTCPSocket) : NetService(), m_pSvr(pSvr), m_pTCPSocket(pTCPSocket), m_watchdog(), m_closed(false) 00032 { 00033 m_pTCPSocket->setOnEvent(this, &HTTPRequestDispatcher::onTCPSocketEvent); 00034 m_watchdog.attach_us<HTTPRequestDispatcher>(this, &HTTPRequestDispatcher::onTimeout, HTTP_REQUEST_TIMEOUT * 1000); 00035 } 00036 00037 HTTPRequestDispatcher::~HTTPRequestDispatcher() 00038 { 00039 close(); 00040 } 00041 00042 void HTTPRequestDispatcher::dispatchRequest() 00043 { 00044 string path; 00045 string meth; 00046 HTTP_METH methCode; 00047 00048 DBG("Dispatching req\r\n"); 00049 00050 if( !getRequest(&path, &meth ) ) 00051 { 00052 close(); 00053 return; //Invalid request 00054 } 00055 00056 if( !meth.compare("GET") ) 00057 { 00058 methCode = HTTP_GET; 00059 } 00060 else if( !meth.compare("POST") ) 00061 { 00062 methCode = HTTP_POST; 00063 } 00064 else if( !meth.compare("HEAD") ) 00065 { 00066 methCode = HTTP_HEAD; 00067 } 00068 else 00069 { 00070 close(); //Parse error 00071 return; 00072 } 00073 00074 DBG("Looking for a handler\r\n"); 00075 00076 map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*) >::iterator it; 00077 // it = m_pSvr->m_lpHandlers.find(rootPath); //We are friends so we can do that 00078 // NEW CODE START: 00079 int root_len = 0; 00080 for (it = m_pSvr->m_lpHandlers.begin(); it != m_pSvr->m_lpHandlers.end(); it++) 00081 { 00082 DBG("Checking %s...\n", (*it).first.c_str()); 00083 root_len = (*it).first.length(); 00084 if ( root_len && 00085 !path.compare( 0, root_len, (*it).first ) && 00086 (path[root_len] == '/' || path[root_len] == '\0')) 00087 { 00088 DBG("Found (%s)\n", (*it).first.c_str()); 00089 // Found! 00090 break; // for 00091 } 00092 } 00093 // NEW CODE END 00094 if((it == m_pSvr->m_lpHandlers.end()) && !(m_pSvr->m_lpHandlers.empty())) 00095 { 00096 DBG("Using default handler\n"); 00097 it = m_pSvr->m_lpHandlers.end(); 00098 it--; //Get the last element 00099 if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler 00100 it = m_pSvr->m_lpHandlers.end(); 00101 root_len = 0; 00102 } 00103 if(it == m_pSvr->m_lpHandlers.end()) 00104 { 00105 DBG("No handler found\n"); 00106 close(); //No handler found 00107 return; 00108 } 00109 00110 DBG("Handler found.\r\n"); 00111 00112 //HTTPRequestHandler* pHdlr = (*it).second(rootPath.c_str(), subPath.c_str(), m_pTCPSocket); 00113 //NEW CODE 1 LINE: 00114 HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, m_pTCPSocket); 00115 m_pTCPSocket = NULL; //We don't own it anymore 00116 00117 switch(methCode) 00118 { 00119 case HTTP_GET: 00120 pHdlr->doGet(); 00121 break; 00122 case HTTP_POST: 00123 pHdlr->doPost(); 00124 break; 00125 case HTTP_HEAD: 00126 pHdlr->doHead(); 00127 break; 00128 } 00129 00130 DBG("Req handled (or being handled)\r\n"); 00131 close(); 00132 } 00133 00134 void HTTPRequestDispatcher::close() //Close socket and destroy data 00135 { 00136 if(m_closed) 00137 return; 00138 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else 00139 m_watchdog.detach(); 00140 if(m_pTCPSocket) //m_pTCPSocket Should only be destroyed if ownership not passed to an handler 00141 { 00142 m_pTCPSocket->resetOnEvent(); 00143 m_pTCPSocket->close(); 00144 delete m_pTCPSocket; //This fn might have been called by this socket (through an event), so DO NOT DESTROY IT HERE 00145 } 00146 NetService::close(); 00147 } 00148 00149 00150 void HTTPRequestDispatcher::onTimeout() //Connection has timed out 00151 { 00152 close(); 00153 } 00154 00155 bool HTTPRequestDispatcher::getRequest(string* path, string* meth) 00156 { 00157 char req[128]; 00158 char c_path[128]; 00159 char c_meth[128]; 00160 const int maxLen = 128; 00161 char* p = req; 00162 //Read Line 00163 int ret; 00164 int len = 0; 00165 for(int i = 0; i < maxLen - 1; i++) 00166 { 00167 ret = m_pTCPSocket->recv(p, 1); 00168 if(!ret) 00169 { 00170 break; 00171 } 00172 if( (len > 1) && *(p-1)=='\r' && *p=='\n' ) 00173 { 00174 p--; 00175 len-=2; 00176 break; 00177 } 00178 else if( *p=='\n' ) 00179 { 00180 len--; 00181 break; 00182 } 00183 p++; 00184 len++; 00185 } 00186 *p = 0; 00187 00188 DBG("Parsing request : %s\r\n", req); 00189 00190 ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path); 00191 if(ret !=2) 00192 return false; 00193 00194 *meth = string(c_meth); 00195 // NEW CODE (old code removed): 00196 *path = string(c_path); 00197 return true; 00198 } 00199 00200 00201 00202 void HTTPRequestDispatcher::onTCPSocketEvent(TCPSocketEvent e) 00203 { 00204 00205 DBG("\r\nEvent %d\r\n", e); 00206 00207 if(m_closed) 00208 { 00209 DBG("\r\nWARN: Discarded\r\n"); 00210 return; 00211 } 00212 00213 switch(e) 00214 { 00215 case TCPSOCKET_READABLE: 00216 m_watchdog.detach(); 00217 m_pTCPSocket->resetOnEvent(); 00218 //Req arrived, dispatch : 00219 dispatchRequest(); 00220 break; 00221 case TCPSOCKET_CONTIMEOUT: 00222 case TCPSOCKET_CONRST: 00223 case TCPSOCKET_CONABRT: 00224 case TCPSOCKET_ERROR: 00225 case TCPSOCKET_DISCONNECTED: 00226 close(); 00227 break; 00228 } 00229 00230 }
Generated on Tue Jul 12 2022 15:37:03 by 1.7.2