httpServer example program for WIZwiki-W7500 Only LED control

Dependents:   httpServer-WIZwiki-W7500

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPConnection.cpp Source File

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 }