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