Changes made for RPC
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 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 Mon Jul 18 2022 11:51:41 by
