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