Adaptation of the HttpServer by user yueee_yt. This version has improved handling of the HTTP headers (**NOTE**: There are limitations with this implementation and it is not fully functional. Use it only as a starting point.)
Dependents: DMSupport DMSupport DMSupport DMSupport
Fork of DM_HttpServer by
HTTPRequestHandler.cpp
00001 /* 00002 Permission is hereby granted, free of charge, to any person obtaining a copy 00003 of this software and associated documentation files (the "Software"), to deal 00004 in the Software without restriction, including without limitation the rights 00005 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00006 copies of the Software, and to permit persons to whom the Software is 00007 furnished to do so, subject to the following conditions: 00008 00009 The above copyright notice and this permission notice shall be included in 00010 all copies or substantial portions of the Software. 00011 00012 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00013 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00014 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00015 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00016 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00018 THE SOFTWARE. 00019 */ 00020 #ifdef _DEBUG_ALL 00021 #define _DEBUG_REQUEST_HANDLER 00022 #endif 00023 00024 #include "HTTPRequestHandler.h" 00025 #include "DMBoard.h" 00026 00027 #include <string.h> 00028 00029 #define HTTP_REQUEST_TIMEOUT 5000 00030 00031 //HTTPRequestHandler::HTTPRequestHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : NetService(), 00032 // m_pTCPSocketConnection(pTCPSocketConnection), m_reqHeaders(), m_respHeaders(), 00033 // m_rootPath(rootPath), m_path(path), m_errc(200), 00034 // m_watchdog(), m_timeout(0),**/ m_closed(false), m_headersSent(false) //OK 00035 HTTPRequestHandler::HTTPRequestHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocketConnection) : 00036 m_pTCPSocketConnection(pTCPSocketConnection), m_reqHeaders(), m_respHeaders(), 00037 m_rootPath(rootPath), m_path(path), m_errc(200), m_closed(false), m_headersSent(false) 00038 { 00039 #ifdef _DEBUG_REQUEST_HANDLER 00040 DMBoard::instance().logger()->printf("+++(HTTPRequestHandler) init \r\n"); 00041 #endif 00042 //Read & parse headers 00043 readHeaders(); 00044 //* m_pTCPSocket->setOnEvent(this, &HTTPRequestHandler::onTCPSocketEvent); 00045 //* setTimeout(HTTP_REQUEST_TIMEOUT); 00046 #ifdef _DEBUG_REQUEST_HANDLER 00047 DMBoard::instance().logger()->printf("+++(HTTPRequestHandler) init end \r\n"); 00048 #endif 00049 } 00050 00051 HTTPRequestHandler::~HTTPRequestHandler() 00052 { 00053 close (); 00054 #ifdef _DEBUG_REQUEST_HANDLER 00055 DMBoard::instance().logger()->printf("+++(HTTPRequestHandler) Destroy end\r\n"); 00056 #endif 00057 } 00058 00059 void HTTPRequestHandler::onTimeout() //Connection has timed out 00060 { 00061 close (); 00062 } 00063 00064 void HTTPRequestHandler::close () //Close socket and destroy data 00065 { 00066 if(m_closed) 00067 return; 00068 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else 00069 /** m_watchdog.detach(); **/ 00070 //* onClose(); 00071 //* m_pTCPSocket->resetOnEvent(); 00072 //* m_pTCPSocket->close(); 00073 //* delete m_pTCPSocket; //Can safely destroy socket 00074 //* NetService::close(); 00075 } 00076 00077 map<string, string>& HTTPRequestHandler::reqHeaders() //const 00078 { 00079 return m_reqHeaders; 00080 } 00081 00082 string& HTTPRequestHandler::path() //const 00083 { 00084 return m_path; 00085 } 00086 00087 int HTTPRequestHandler::dataLen() const 00088 { 00089 map<string,string>::const_iterator it; 00090 it = m_reqHeaders.find("Content-Length"); 00091 if( it == m_reqHeaders.end() ) { 00092 return 0; 00093 } 00094 return atoi((*it).second.c_str()); //return 0 if parse fails, so that's fine 00095 } 00096 00097 int HTTPRequestHandler::readData(char* buf, int len) 00098 { 00099 return m_pTCPSocketConnection->recv(buf, len); 00100 } 00101 00102 string& HTTPRequestHandler::rootPath() //const 00103 { 00104 return m_rootPath; 00105 } 00106 00107 void HTTPRequestHandler::setErrCode(int errc) 00108 { 00109 m_errc = errc; 00110 } 00111 00112 void HTTPRequestHandler::setContentLen(int len) 00113 { 00114 char len_str[6] = {0}; 00115 snprintf(len_str, 6, "%d", len); 00116 respHeaders()["Content-Length"] = len_str; 00117 } 00118 00119 map<string, string>& HTTPRequestHandler::respHeaders() 00120 { 00121 return m_respHeaders; 00122 } 00123 00124 int HTTPRequestHandler::writeData(const char* buf, int len) 00125 { 00126 if(!m_headersSent) { 00127 m_headersSent = true; 00128 writeHeaders(); 00129 } 00130 00131 return m_pTCPSocketConnection->send((char *)buf, len); 00132 } 00133 /** 00134 void HTTPRequestHandler::setTimeout(int ms) 00135 { 00136 m_timeout = 1000*ms; 00137 resetTimeout(); 00138 } 00139 **/ 00140 /** 00141 void HTTPRequestHandler::resetTimeout() 00142 { 00143 m_watchdog.detach(); 00144 m_watchdog.attach_us<HTTPRequestHandler>(this, &HTTPRequestHandler::onTimeout, m_timeout); 00145 } 00146 **/ 00147 00148 void HTTPRequestHandler::readHeaders() 00149 { 00150 static char line[128]; 00151 static char key[128]; 00152 static char value[128]; 00153 00154 // Prepare cache 00155 read_cache_t* cache = (read_cache_t*)malloc(sizeof(read_cache_t)); 00156 cache->size = 1024; 00157 cache->num = cache->pos = 0; 00158 00159 while( readLineCached(line, 128, cache) > 0) { //if == 0, it is an empty line = end of headers 00160 int n = sscanf(line, "%[^:]: %[^\n]", key, value); 00161 if ( n == 2 ) { 00162 #ifdef _DEBUG_REQUEST_HANDLER 00163 DMBoard::instance().logger()->printf("\r\n+++(HTTPRequestHandler)Read header : %s : %s\r\n", key, value); 00164 #endif 00165 m_reqHeaders[key] = value; 00166 } 00167 //TODO: Impl n==1 case (part 2 of previous header) 00168 } 00169 free(cache); 00170 } 00171 00172 void HTTPRequestHandler::writeHeaders() //Called at the first writeData call 00173 { 00174 static char line[128]; 00175 00176 //Response line 00177 snprintf(line, 128, "HTTP/1.1 %d MbedInfo\r\n", m_errc); //Not a violation of the standard not to include the descriptive text 00178 m_pTCPSocketConnection->send(line, strlen(line)); 00179 00180 map<string,string>::iterator it; 00181 while( !m_respHeaders.empty() ) { 00182 it = m_respHeaders.begin(); 00183 snprintf(line, 128, "%s: %s\r\n", (*it).first.c_str(), (*it).second.c_str() ); 00184 #ifdef _DEBUG_REQUEST_HANDLER 00185 DMBoard::instance().logger()->printf("\r\n+++(HTTPRequestHandler)%s", line); 00186 #endif 00187 m_pTCPSocketConnection->send(line, strlen(line)); 00188 m_respHeaders.erase(it); 00189 } 00190 m_pTCPSocketConnection->send("\r\n",2); //End of head 00191 } 00192 00193 int HTTPRequestHandler::readLine(char* str, int maxLen) 00194 { 00195 int ret; 00196 int len = 0; 00197 for(int i = 0; i < maxLen - 1; i++) { 00198 ret = m_pTCPSocketConnection->recv(str, 1); 00199 if(!ret) { 00200 break; 00201 } 00202 if( (len > 1) && *(str-1)=='\r' && *str=='\n' ) { 00203 str--; 00204 len-=2; 00205 break; 00206 } else if( *str=='\n' ) { 00207 len--; 00208 break; 00209 } 00210 str++; 00211 len++; 00212 } 00213 *str = 0; 00214 return len; 00215 } 00216 00217 00218 int HTTPRequestHandler::readLineCached(char* str, int maxLen, read_cache_t* cache) 00219 { 00220 maxLen--; // leave room for null termination 00221 00222 int len = 0; 00223 int i = 0; 00224 bool found = false; 00225 while (i < maxLen && !found) { 00226 if (cache->num <= cache->pos) { 00227 // get something to process 00228 int ret = m_pTCPSocketConnection->recv(cache->buff, cache->size); 00229 if(ret == -1) { 00230 // error 00231 break; 00232 } else if (ret == 0) { 00233 // didn't get anything to process, try again 00234 continue; 00235 } 00236 cache->num = ret; 00237 cache->pos = 0; 00238 } 00239 00240 // have >0 bytes to process 00241 while ((cache->pos < cache->num) && (i < maxLen)) { 00242 *str = cache->buff[cache->pos++]; 00243 if( (len > 1) && *(str-1)=='\r' && *str=='\n' ) { 00244 str--; 00245 len-=2; 00246 found = true; 00247 break; 00248 } else if( *str=='\n' ) { 00249 len--; 00250 found = true; 00251 break; 00252 } 00253 str++; 00254 len++; 00255 } 00256 } 00257 *str = 0; 00258 return len; 00259 } 00260 00261 /** 00262 void HTTPRequestHandler::onTCPSocketEvent(TCPSocketEvent e) 00263 { 00264 //printf("\r\nEvent %d in HTTPRequestHandler\r\n", e); 00265 printf("\r\n+++(HTTPRequestHandler)Event in HTTPRequestHandler\r\n"); 00266 00267 if(m_closed) 00268 { 00269 printf("\r\n+++(HTTPRequestHandler)WARN: Discarded\r\n"); 00270 return; 00271 } 00272 00273 switch(e) 00274 { 00275 case TCPSOCKET_READABLE: 00276 resetTimeout(); 00277 onReadable(); 00278 break; 00279 case TCPSOCKET_WRITEABLE: 00280 resetTimeout(); 00281 onWriteable(); 00282 break; 00283 case TCPSOCKET_CONTIMEOUT: 00284 case TCPSOCKET_CONRST: 00285 case TCPSOCKET_CONABRT: 00286 case TCPSOCKET_ERROR: 00287 case TCPSOCKET_DISCONNECTED: 00288 DBG("\r\nConnection error in handler\r\n"); 00289 close(); 00290 break; 00291 } 00292 } 00293 **/
Generated on Sat Jul 16 2022 20:32:10 by 1.7.2