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