Library for httpserver
Fork of httpServer_with_Ethernt by
Embed:
(wiki syntax)
Show/hide line numbers
HTTPConnection.cpp
00001 /* HTTPConnection.cpp */ 00002 00003 #include "mbed.h" 00004 #include "HTTPConnection.h" 00005 //#define DEBUG 00006 #include "hl_debug.h" 00007 00008 #include <vector> 00009 using std::vector; 00010 00011 using std::string; 00012 00013 00014 00015 const struct HTTPRequestConfig { 00016 const char* request_string; 00017 HTTPRequestType request_type; 00018 } g_requestConfig[] = { 00019 { "GET", HTTP_RT_GET }, 00020 { "POST", HTTP_RT_POST}, 00021 { "PUT", HTTP_RT_PUT}, 00022 { "OPTIONS",HTTP_RT_OPTIONS}, 00023 { "HEAD", HTTP_RT_HEAD}, 00024 { "DELETE", HTTP_RT_DELETE}, 00025 { "TRACE", HTTP_RT_TRACE}, 00026 { "CONNECT",HTTP_RT_CONNECT} 00027 }; 00028 00029 00030 HTTPConnection::HTTPConnection(TCPSocketConnection& clnt) : m_Tcp(clnt) 00031 { 00032 } 00033 00034 00035 HTTPConnection::~HTTPConnection() 00036 { 00037 close(); 00038 } 00039 00040 void HTTPConnection::close() 00041 { 00042 m_Msg.headers.clear(); 00043 } 00044 00045 int HTTPConnection::poll() 00046 { 00047 static char buffer[256] = {}; 00048 int rcvd= 0; 00049 int ret = 0; 00050 int attri_len = 0; 00051 00052 INFO("Waiting for new data in connection"); 00053 // Try receiving request line 00054 rcvd = receiveLine(buffer, 255, 3000); 00055 if (rcvd == -1) { 00056 // there was an error, probably the connection was closed, so close this connection as well 00057 INFO("No more data available. Will close this connection now."); 00058 close(); 00059 return -1; 00060 } 00061 00062 // The Request has not yet been received so try it 00063 rcvd = parse(buffer); 00064 if (rcvd == -1) { 00065 // Invalid content received, so close the connection 00066 INFO("Invalid message received, so sending negative response and closing connection !"); 00067 //sprintf(buffer,"HTTP/1.1 400 BadRequest\n\rContent-Length: %d\n\rContent-Type: text\n\r\n\r\n\r",0); 00068 m_Tcp.set_blocking(true, 1500); 00069 //m_Tcp.send(buffer,strlen(buffer)); 00070 close(); 00071 rcvd = -1; 00072 return -1; 00073 } 00074 // The request has been received, try receive the body 00075 while(rcvd > 0) { 00076 rcvd = receiveLine((char*)buffer, 255, 3000); 00077 // First check if we received an empty line. This would indicate the end of the message or message body. 00078 if (rcvd < 0) { 00079 // there was an empty line, so we can start with performing the request 00080 INFO("Request Header was received completely. Performing request."); 00081 rcvd = 0; 00082 break; 00083 } 00084 else { 00085 // add message body 00086 ret = parseHeader(buffer); 00087 if (ret == 0) { 00088 00089 } 00090 else { 00091 attri_len = ret; 00092 } 00093 } 00094 } 00095 00096 //Receive attribute data 00097 if( attri_len != 0 ) 00098 { 00099 m_Tcp.receive( m_Msg.attri, attri_len ); 00100 } 00101 00102 INFO("Leaving poll function!"); 00103 return rcvd; 00104 } 00105 00106 int HTTPConnection::receiveLine(char* szLine, int nMaxLen, int nTimeout, char cLineTerm) 00107 { 00108 if ((szLine == NULL) || (nMaxLen == 0)) 00109 return -1; 00110 00111 szLine[0] = 0; 00112 m_Tcp.set_blocking(false, 1500); 00113 00114 if (!m_Tcp.is_connected()) { 00115 error("NOT COnnected anymore"); 00116 return -1; 00117 } 00118 Timer tm; 00119 int i; 00120 00121 // Try to receive up to the max number of characters 00122 for (i = 0 ; i < nMaxLen-1 ; i++) { 00123 int c; 00124 c = m_Tcp.receive( szLine + i, 1 ); 00125 // Check that - if no character was currently received - the timeout period is reached. 00126 if ((c == 0) || (c==-1)) { 00127 // no character was read, so check if operation timed out 00128 //if (tm.read_ms() > nTimeout) { 00129 // Operation timed out 00130 //INFO("Timeout occured in function 'receiveLine'."); 00131 return -1; 00132 //} 00133 } 00134 00135 // Check if line terminating character was received 00136 if (szLine[i] == cLineTerm) 00137 { 00138 break; 00139 } 00140 } 00141 00142 // Terminate with \0 00143 szLine[i] = 0; 00144 00145 // Trim for '\r' linefeed at the end 00146 if( (i >0) && (szLine[i-1] == '\r')) { 00147 i--; 00148 szLine[i] = 0; 00149 } 00150 00151 // return number of characters received in the line or return -2 if an empty line was received 00152 if ((i == 0) || ((i==1) &&(szLine[0] == '\r'))) 00153 { 00154 // empty line received, so return -2 00155 return -2; 00156 } 00157 return i; 00158 } 00159 00160 int HTTPConnection::parse(char* buffer) 00161 { 00162 // Check if buffer is invalid or its content not long enough. 00163 if ((buffer == NULL) || (strlen(buffer) < 4)) { 00164 ERR("Buffer content is invalid or too short."); 00165 return -1; 00166 } 00167 00168 std::vector<std::string> args; 00169 args.clear(); 00170 00171 int argno = 0; 00172 // decompose string into a list of arguments 00173 char s = 0; // current starting char 00174 int nLen = strlen(buffer)+1; 00175 00176 00177 //for(int i = 0; i < nLen; i++) 00178 //printf("%d : %c\r\n", i, buffer[i]); 00179 00180 00181 for (int i = 0 ; i < nLen ; i++) { 00182 if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) { 00183 // new arg found 00184 buffer[i] = 0; 00185 if (argno++ == 1) { 00186 // its the uri 00187 // parse the uri args 00188 parseUriArgs(&buffer[s], m_Msg.args); 00189 } 00190 INFO("Found argument \"%s\"", &buffer[s]); 00191 args.push_back(&buffer[s]); 00192 s = i+1; 00193 } 00194 } 00195 00196 // store the uri and the HTTP version 00197 m_Msg.uri = args[1]; 00198 m_Msg.version = args[2]; 00199 00200 // Find matching request type 00201 for (int i = 0 ; i < sizeof(g_requestConfig)/sizeof(struct HTTPRequestConfig) ; i++) { 00202 if (args.at(0) == g_requestConfig[i].request_string) { 00203 m_Msg.request = g_requestConfig[i].request_type; 00204 } 00205 } 00206 args.clear(); 00207 00208 return 1; 00209 } 00210 00211 00212 int HTTPConnection::parseHeader(char *buffer) 00213 { 00214 // Check if the buffer is invalid or if the content is too short to be meaningful 00215 if ((strlen(buffer) <3) || (buffer == NULL)) 00216 return -1; 00217 00218 //Find Content length 00219 if(strncmp(buffer, "Content-Length", 14) == 0) 00220 { 00221 m_Msg.attri_len = atoi(&buffer[16]); 00222 return m_Msg.attri_len; 00223 } 00224 /* 00225 for (int i = 0 ; i < buflen ; i++) { 00226 if (buffer[i] == ':') { 00227 // touple found 00228 buffer[i] = 0; 00229 value_start = i+1; 00230 m_Msg.headers[buffer] = &buffer[value_start]; 00231 00232 INFO("Header name=\"%s\" : value=\"%s\".", buffer, &buffer[value_start]); 00233 return 0; 00234 } 00235 } 00236 */ 00237 return 0; 00238 //ERR("Did not recieve a valid header : \"%s\".", buffer); 00239 //return -1; 00240 } 00241 00242 int HTTPConnection::parseUriArgs(char *buffer, map<string,string>&args) 00243 { 00244 // Check if the buffer is invalid or if the content is too short to be meaningful 00245 if ((strlen(buffer) <3) || (buffer == NULL)) 00246 return -1; 00247 00248 int args_start = -1; 00249 int value_start = -1; 00250 int buflen = strlen(buffer) +1; 00251 const char* argname = NULL; 00252 const char* valuename = NULL; 00253 for (int i = 0; i < buflen ; i++) { 00254 if (args_start == -1) { // args section not yet found 00255 if (buffer[i] == '?') { // starts with a question mark, so got it 00256 buffer[i] = 0; 00257 args_start = i; // set the start of the args section 00258 INFO("Argument section found !"); 00259 } 00260 } 00261 else { // search arg-value touples 00262 if (argname == NULL) { // arg-name found ? 00263 if (buffer[i] == '=') { 00264 // yes, separate the arg-name 00265 buffer[i] = 0; 00266 argname = &buffer[args_start]; 00267 value_start = i+1; 00268 INFO("Argument name %s", argname); 00269 } 00270 } 00271 else { // search for end of value 00272 if ((buffer[i] == '&') || (buffer[i] == 0) || (buffer[i] == '\r') || (buffer[i] == '\n')) { 00273 buffer[i] = 0; 00274 valuename = &buffer[value_start]; 00275 INFO("Argument value %s", valuename); 00276 args[argname] = valuename; 00277 // reset all indicators 00278 argname = NULL; 00279 valuename = NULL; 00280 } 00281 } 00282 } 00283 } 00284 00285 00286 return 0; 00287 } 00288 00289
Generated on Wed Jul 13 2022 04:13:19 by
