Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of httpServer by
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 00:31:04 by
1.7.2
