Darran Shepherd
/
AutoIpNetStack
Net stack with AutoIP enabled
Embed:
(wiki syntax)
Show/hide line numbers
HTTPRequestHandler.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 "HTTPRequestHandler.h" 00025 00026 #include <string.h> 00027 00028 //#define __DEBUG 00029 #include "dbg/dbg.h" 00030 00031 #define HTTP_REQUEST_TIMEOUT 5000 00032 00033 HTTPRequestHandler::HTTPRequestHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : NetService(), 00034 m_pTCPSocket(pTCPSocket), m_reqHeaders(), m_respHeaders(), 00035 m_rootPath(rootPath), m_path(path), m_errc(200), 00036 m_watchdog(), m_timeout(0), m_closed(false), m_headersSent(false) //OK 00037 { 00038 //Read & parse headers 00039 readHeaders(); 00040 m_pTCPSocket->setOnEvent(this, &HTTPRequestHandler::onTCPSocketEvent); 00041 setTimeout(HTTP_REQUEST_TIMEOUT); 00042 } 00043 00044 HTTPRequestHandler::~HTTPRequestHandler() 00045 { 00046 close(); 00047 } 00048 00049 void HTTPRequestHandler::onTimeout() //Connection has timed out 00050 { 00051 close(); 00052 } 00053 00054 void HTTPRequestHandler::close() //Close socket and destroy data 00055 { 00056 if(m_closed) 00057 return; 00058 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else 00059 m_watchdog.detach(); 00060 onClose(); 00061 m_pTCPSocket->resetOnEvent(); 00062 m_pTCPSocket->close(); 00063 delete m_pTCPSocket; //Can safely destroy socket 00064 NetService::close(); 00065 } 00066 00067 map<string, string>& HTTPRequestHandler::reqHeaders() //const 00068 { 00069 return m_reqHeaders; 00070 } 00071 00072 string& HTTPRequestHandler::path() //const 00073 { 00074 return m_path; 00075 } 00076 00077 int HTTPRequestHandler::dataLen() const 00078 { 00079 map<string,string>::iterator it; 00080 it = m_reqHeaders.find("Content-Length"); 00081 if( it == m_reqHeaders.end() ) 00082 { 00083 return 0; 00084 } 00085 return atoi((*it).second.c_str()); //return 0 if parse fails, so that's fine 00086 } 00087 00088 int HTTPRequestHandler::readData(char* buf, int len) 00089 { 00090 return m_pTCPSocket->recv(buf, len); 00091 } 00092 00093 string& HTTPRequestHandler::rootPath() //const 00094 { 00095 return m_rootPath; 00096 } 00097 00098 void HTTPRequestHandler::setErrCode(int errc) 00099 { 00100 m_errc = errc; 00101 } 00102 00103 void HTTPRequestHandler::setContentLen(int len) 00104 { 00105 char len_str[6] = {0}; 00106 sprintf(len_str, "%d", len); 00107 respHeaders()["Content-Length"] = len_str; 00108 } 00109 00110 map<string, string>& HTTPRequestHandler::respHeaders() 00111 { 00112 return m_respHeaders; 00113 } 00114 00115 int HTTPRequestHandler::writeData(const char* buf, int len) 00116 { 00117 if(!m_headersSent) 00118 { 00119 m_headersSent = true; 00120 writeHeaders(); 00121 } 00122 00123 return m_pTCPSocket->send(buf, len); 00124 } 00125 00126 void HTTPRequestHandler::setTimeout(int ms) 00127 { 00128 m_timeout = 1000*ms; 00129 resetTimeout(); 00130 } 00131 00132 void HTTPRequestHandler::resetTimeout() 00133 { 00134 m_watchdog.detach(); 00135 m_watchdog.attach_us<HTTPRequestHandler>(this, &HTTPRequestHandler::onTimeout, m_timeout); 00136 } 00137 00138 00139 void HTTPRequestHandler::readHeaders() 00140 { 00141 static char line[128]; 00142 static char key[128]; 00143 static char value[128]; 00144 while( readLine(line, 128) > 0) //if == 0, it is an empty line = end of headers 00145 { 00146 int n = sscanf(line, "%[^:]: %[^\n]", key, value); 00147 if ( n == 2 ) 00148 { 00149 DBG("\r\nRead header : %s : %s\r\n", key, value); 00150 m_reqHeaders[key] = value; 00151 } 00152 //TODO: Impl n==1 case (part 2 of previous header) 00153 } 00154 } 00155 00156 void HTTPRequestHandler::writeHeaders() //Called at the first writeData call 00157 { 00158 static char line[128]; 00159 00160 //Response line 00161 sprintf(line, "HTTP/1.1 %d MbedInfo\r\n", m_errc); //Not a violation of the standard not to include the descriptive text 00162 m_pTCPSocket->send(line, strlen(line)); 00163 00164 map<string,string>::iterator it; 00165 while( !m_respHeaders.empty() ) 00166 { 00167 it = m_respHeaders.begin(); 00168 sprintf(line, "%s: %s\r\n", (*it).first.c_str(), (*it).second.c_str() ); 00169 DBG("\r\n%s", line); 00170 m_pTCPSocket->send(line, strlen(line)); 00171 m_respHeaders.erase(it); 00172 } 00173 m_pTCPSocket->send("\r\n",2); //End of head 00174 } 00175 00176 int HTTPRequestHandler::readLine(char* str, int maxLen) 00177 { 00178 int ret; 00179 int len = 0; 00180 for(int i = 0; i < maxLen - 1; i++) 00181 { 00182 ret = m_pTCPSocket->recv(str, 1); 00183 if(!ret) 00184 { 00185 break; 00186 } 00187 if( (len > 1) && *(str-1)=='\r' && *str=='\n' ) 00188 { 00189 str--; 00190 len-=2; 00191 break; 00192 } 00193 else if( *str=='\n' ) 00194 { 00195 len--; 00196 break; 00197 } 00198 str++; 00199 len++; 00200 } 00201 *str = 0; 00202 return len; 00203 } 00204 00205 void HTTPRequestHandler::onTCPSocketEvent(TCPSocketEvent e) 00206 { 00207 00208 DBG("\r\nEvent %d in HTTPRequestHandler\r\n", e); 00209 00210 if(m_closed) 00211 { 00212 DBG("\r\nWARN: Discarded\r\n"); 00213 return; 00214 } 00215 00216 switch(e) 00217 { 00218 case TCPSOCKET_READABLE: 00219 resetTimeout(); 00220 onReadable(); 00221 break; 00222 case TCPSOCKET_WRITEABLE: 00223 resetTimeout(); 00224 onWriteable(); 00225 break; 00226 case TCPSOCKET_CONTIMEOUT: 00227 case TCPSOCKET_CONRST: 00228 case TCPSOCKET_CONABRT: 00229 case TCPSOCKET_ERROR: 00230 case TCPSOCKET_DISCONNECTED: 00231 DBG("\r\nConnection error in handler\r\n"); 00232 close(); 00233 break; 00234 } 00235 00236 }
Generated on Tue Jul 12 2022 15:37:03 by 1.7.2