ソースの整理中ですが、利用はできます。

Dependencies:   EthernetInterface HttpServer TextLCD mbed-rpc mbed-rtos mbed Socket lwip-eth lwip-sys lwip

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPRequestHandler.cpp Source File

HTTPRequestHandler.cpp

00001 /*
00002 Permission is hereby granted, free of charge, to any person obtaining a copy
00003 of this software and associated documentation files (the "Software"), to deal
00004 in the Software without restriction, including without limitation the rights
00005 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00006 copies of the Software, and to permit persons to whom the Software is
00007 furnished to do so, subject to the following conditions:
00008 
00009 The above copyright notice and this permission notice shall be included in
00010 all copies or substantial portions of the Software.
00011 
00012 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00013 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00014 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00015 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00016 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00017 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00018 THE SOFTWARE.
00019 */
00020 //#define _DEBUG_REQUEST_HANDLER
00021 //#pragma O0
00022 #include "HTTPRequestHandler.h"
00023 
00024 #include <string.h>
00025 
00026 //#define HTTP_REQUEST_TIMEOUT 5000
00027 //#define HTTP_POST_REQUEST_TIMEOUT 2000
00028 #define READ_SIZE 128
00029 //HTTPRequestHandler::HTTPRequestHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : NetService(),
00030 //   m_pTCPSocketConnection(pTCPSocketConnection), m_reqHeaders(), m_respHeaders(),
00031 //   m_rootPath(rootPath), m_path(path), m_errc(200),
00032 //   m_watchdog(), m_timeout(0),**/ m_closed(false), m_headersSent(false) //OK
00033 HTTPRequestHandler::HTTPRequestHandler(const char* rootPath, const char* path, TCPSocketConnection* pTCPSocketConnection) :
00034     m_pTCPSocketConnection(pTCPSocketConnection), /*m_reqHeaders(), m_respHeaders(),*/
00035     m_rootPath(rootPath), m_path(path), m_errc(200), m_closed(false), m_headersSent(false)
00036 {
00037 #ifdef _DEBUG_REQUEST_HANDLER
00038     printf("+++(HTTPRequestHandler) init \r\n");
00039 #endif
00040     req_headers_count=0;
00041     resp_headers_count=0;
00042     //Read & parse headers
00043     readHeaders();
00044 //*  m_pTCPSocket->setOnEvent(this, &HTTPRequestHandler::onTCPSocketEvent);
00045 //*  setTimeout(HTTP_REQUEST_TIMEOUT);
00046 #ifdef _DEBUG_REQUEST_HANDLER
00047     printf("+++(HTTPRequestHandler) init end \r\n");
00048 #endif
00049 }
00050 
00051 HTTPRequestHandler::~HTTPRequestHandler()
00052 {
00053     close ();
00054 #ifdef _DEBUG_REQUEST_HANDLER
00055     printf("+++(HTTPRequestHandler) Destroy end\r\n");
00056 #endif
00057 }
00058 
00059 void HTTPRequestHandler::onTimeout() //Connection has timed out
00060 {
00061     close ();
00062 }
00063 
00064 void HTTPRequestHandler::close () //Close socket and destroy data
00065 {
00066     if(m_closed)
00067         return;
00068     m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
00069     /**  m_watchdog.detach(); **/
00070 //*  onClose();
00071 //*  m_pTCPSocket->resetOnEvent();
00072 //*m_pTCPSocketConnection->close();
00073 //* delete m_pTCPSocketConnection; //Can safely destroy socket
00074 //*  NetService::close();
00075 }
00076 
00077 //map<string, string>& HTTPRequestHandler::reqHeaders() //const
00078 //{
00079 //    return m_reqHeaders;
00080 //}
00081 void HTTPRequestHandler::reqHeaders(string *key,string *value,unsigned char *count) //const
00082 {
00083     for(int i=0; i<10; i++) {
00084         key[i]=req_headers_key[i];
00085         value[i]=req_headers_value[i];
00086     }
00087     *count=req_headers_count;
00088 //    return m_reqHeaders;
00089 }
00090 
00091 string& HTTPRequestHandler::path() //const
00092 {
00093     return m_path;
00094 }
00095 
00096 int HTTPRequestHandler::dataLen() const
00097 {
00098     int ret=0;
00099     if (clength>0) ret=clength;
00100     //   map<string,string>::iterator it;
00101     // it = m_reqHeaders.find("Content-Length");
00102     //  if( it == m_reqHeaders.end() ) {
00103     //      return 0;
00104     //  }
00105     //  return atoi((*it).second.c_str()); //return 0 if parse fails, so that's fine
00106     return ret;
00107 }
00108 
00109 int HTTPRequestHandler::readData(char* buf, int len)
00110 {
00111     return m_pTCPSocketConnection->receive(buf, len);
00112 }
00113 
00114 string& HTTPRequestHandler::rootPath() //const
00115 {
00116     return m_rootPath;
00117 }
00118 
00119 void HTTPRequestHandler::setErrCode(int errc)
00120 {
00121     m_errc = errc;
00122 }
00123 
00124 void HTTPRequestHandler::setContentLen(int len)
00125 {
00126     char len_str[7] = {0};
00127 //#ifdef _DEBUG_REQUEST_HANDLER
00128     printf( "+++(HTTPRequestHandler)Content-Length %d \r\n", len);
00129 //#endif
00130     sprintf(len_str, "%d", len);
00131 //    respHeaders()["Content-Length"] = len_str;
00132     addRespHeaders("Content-Length",string(len_str));
00133 }
00134 
00135 //map<string, string>& HTTPRequestHandler::respHeaders()
00136 //{
00137 //    return m_respHeaders;
00138 //}
00139 
00140 void HTTPRequestHandler::respHeaders(string *key,string *value,unsigned char *count )
00141 {
00142     for(int i=0; i<10; i++) {
00143         key[i]=resp_headers_key[i];
00144         value[i]=resp_headers_value[i];
00145     }
00146     *count=resp_headers_count;
00147 }
00148 
00149 
00150 int HTTPRequestHandler::writeData(const char* buf, int len)
00151 {
00152     if(!m_headersSent) {
00153         m_headersSent = true;
00154         writeHeaders();
00155     }
00156     return  m_pTCPSocketConnection->send((char *)buf, len);
00157 }
00158 /**
00159 void HTTPRequestHandler::setTimeout(int ms)
00160 {
00161   m_timeout = 1000*ms;
00162   resetTimeout();
00163 }
00164 **/
00165 /**
00166 void HTTPRequestHandler::resetTimeout()
00167 {
00168   m_watchdog.detach();
00169   m_watchdog.attach_us<HTTPRequestHandler>(this, &HTTPRequestHandler::onTimeout, m_timeout);
00170 }
00171 **/
00172 
00173 void HTTPRequestHandler::readHeaders()
00174 {
00175     static char line[128];
00176     static char key[128];
00177     static char value[128];
00178     char *p;
00179     chunkmode=false;
00180     req_headers_count=0;
00181     resp_headers_count=0;
00182     while( readLine(line, 128) > 0) { //if == 0, it is an empty line = end of headers
00183         int n = sscanf(line, "%[^:]: %[^\n]", key, value);
00184         if ( n == 2 ) {
00185 #ifdef _DEBUG_REQUEST_HANDLER
00186             printf("+++(HTTPRequestHandler)Read header : %s : %s\r\n", key, value);
00187 #endif
00188             //    m_reqHeaders[key] = value;
00189             if(req_headers_count<10) {
00190                 req_headers_key[req_headers_count]=string(key);
00191                 req_headers_value[req_headers_count]=string(value);
00192                 req_headers_count++;
00193             }
00194             //Check Content Length
00195             for(p=&key[0]; p<(&key[0]+strlen(key)); p++) {
00196                 if((*p>0x60)&&(*p<0x7b))*p=*p-0x20;
00197             }
00198 #ifdef _DEBUG_REQUEST_SERVER_H
00199             printf("+++(HTTPRequestHandler) HEADER %s\r\n",key);
00200 #endif
00201             if(strcmp(key,"CONTENT-LENGTH")==0) {
00202                 sscanf(value,"%d",&clength);
00203             } else if(strcmp(key,"TRANSFER-ENCODING")==0) {
00204                 for(p=&value[0]; p<(&value[0]+strlen(value)); p++) {
00205                     if((*p>0x60)&&(*p<0x7b))*p=*p-0x20;
00206                 }
00207                 if(strcmp(value,"CHUNKED")==0)chunkmode=true;
00208             }
00209         }
00210         //TODO: Impl n==1 case (part 2 of previous header)
00211     }
00212 }
00213 
00214 void HTTPRequestHandler::readReqData()
00215 {
00216     int i;
00217     //ReadHeader
00218 #ifdef _DEBUG_REQUEST_SERVER_H
00219     printf("+++(HTTPRequestHandler)content-length: %d \r\n",cont_length);
00220     if(chunkmode==true)printf("+++(HTTPRequestHandler)CHUNK Transfer \r\n");
00221     else printf("+++(HTTPRequestHandler)NO CHUNK Transfer \r\n");
00222 #endif
00223 //   m_pTCPSocketConnection->set_blocking(true,HTTP_POST_REQUEST_TIMEOUT);
00224     char buffer[READ_SIZE+1];
00225     if(chunkmode==false) {
00226         //no chunked mode
00227         for(;;) {
00228             if(clength>READ_SIZE) {
00229                 i=m_pTCPSocketConnection->receive(buffer,READ_SIZE);
00230                 buffer[READ_SIZE]=0x0;
00231                 m_reqData.append(string(buffer));
00232                 clength-=READ_SIZE;
00233             } else {
00234                 i=m_pTCPSocketConnection->receive(buffer, clength);
00235                 buffer[clength]=0x0;
00236                 m_reqData.append(string(buffer));
00237                 break;
00238             }
00239         }
00240         if(i>0)printf("Success \r\n");
00241     } else {
00242         //chunked mode
00243         int chunk_size;
00244 
00245         for(;;) {
00246             i=readLine(buffer,20);
00247             printf("chunk :%s:\r\n",buffer);
00248             sscanf(buffer,"%x",&chunk_size);
00249             printf("chunk_size = %d \r\n",chunk_size);
00250             if(chunk_size==0)break;
00251             for(;;) {
00252                 if(chunk_size>READ_SIZE) {
00253                     i=m_pTCPSocketConnection->receive(buffer, READ_SIZE);
00254                     buffer[READ_SIZE]=0x0;
00255                     m_reqData.append(string(buffer));
00256                     chunk_size-=READ_SIZE;
00257                 } else {
00258                     i=m_pTCPSocketConnection->receive(buffer, chunk_size);
00259                     buffer[chunk_size]=0x0;
00260                     m_reqData.append(string(buffer));
00261                     break;
00262                 }
00263             }
00264             i=m_pTCPSocketConnection->receive(buffer,2); //\r\n ro read
00265         }
00266 //   i=readLine(buffer,20);//dummy
00267     }
00268 //        m_pTCPSocketConnection->set_blocking(false);
00269 //        while(m_pTCPSocketConnection->receive(buffer,1)>0){}
00270 //     m_pTCPSocketConnection->set_blocking(false);
00271 //    printf("%s \r\n",m_reqData.c_str());
00272 }
00273 
00274 void HTTPRequestHandler::writeHeaders() //Called at the first writeData call
00275 {
00276     char line[128]= {0};
00277     int i;
00278     //Response line
00279     //printf("Hdebug e1\r\n");
00280     //m_pTCPSocketConnection->receive(line, 1);
00281     //printf("%d \r\n",line[0]);
00282 
00283     sprintf(line, "HTTP/1.1 %d OK\r\n", m_errc); //Not a violation of the standard not to include the descriptive text
00284     //printf("debug e2 %d:%s \r\n",strlen(line),line);
00285     //if(m_pTCPSocketConnection->is_connected()==true) {
00286     //    printf("Connect \r\n");
00287     //} else {
00288     //    printf("disconnected \r\n");
00289     //}
00290     //return;
00291     m_pTCPSocketConnection->send(line, strlen(line));
00292 //    map<string,string>::iterator it;
00293     //printf("%d debug e3 \r\n",resp_headers_count);
00294     for(i=0; i<resp_headers_count; i++) {
00295 //    while( !m_respHeaders.empty() ) {
00296 //        it = m_respHeaders.begin();
00297 //        sprintf(line, "%s: %s\r\n", (*it).first.c_str(), (*it).second.c_str() );
00298 //        printf("debug e\r\n");
00299         sprintf(line, "%s: %s\r\n", resp_headers_key[i].c_str(),resp_headers_value[i].c_str());
00300 //        printf("debug e2 %s %d\r\n",line,strlen(line));
00301 #ifdef _DEBUG_REQUEST_HANDLER
00302         printf("\r\n+++(HTTPRequestHandler)Write header %s \r\n", line);
00303 #endif
00304         m_pTCPSocketConnection->send(line, strlen(line));
00305 //        m_respHeaders.erase(it);
00306     }
00307     m_pTCPSocketConnection->send("\r\n",2); //End of head
00308 }
00309 
00310 void HTTPRequestHandler::addRespHeaders(string key,string value)
00311 {
00312     if(resp_headers_count<10) {
00313         resp_headers_key[resp_headers_count]=string(key);
00314         resp_headers_value[resp_headers_count]=string(value);
00315         resp_headers_count++;
00316     } else {
00317         printf("MAX over resp_headers_num \r\n");
00318     }
00319 }
00320 
00321 int HTTPRequestHandler::readLine(char* str, int maxLen)
00322 {
00323     int ret;
00324     int len = 0;
00325     for(int i = 0; i < maxLen - 1; i++) {
00326         ret = m_pTCPSocketConnection->receive(str, 1);
00327         if(!ret) {
00328             break;
00329         }
00330         if( (len > 1) && *(str-1)=='\r' && *str=='\n' ) {
00331             str--;
00332             len-=2;
00333             break;
00334         } else if( *str=='\n' ) {
00335             len--;
00336             break;
00337         }
00338         str++;
00339         len++;
00340     }
00341     *str = 0;
00342     return len;
00343 }
00344 /**
00345 void HTTPRequestHandler::onTCPSocketEvent(TCPSocketEvent e)
00346 {
00347   //printf("\r\nEvent %d in HTTPRequestHandler\r\n", e);
00348   printf("\r\n+++(HTTPRequestHandler)Event in HTTPRequestHandler\r\n");
00349 
00350   if(m_closed)
00351   {
00352     printf("\r\n+++(HTTPRequestHandler)WARN: Discarded\r\n");
00353     return;
00354   }
00355 
00356   switch(e)
00357   {
00358         case TCPSOCKET_READABLE:
00359     resetTimeout();
00360    onReadable();
00361     break;
00362   case TCPSOCKET_WRITEABLE:
00363     resetTimeout();
00364     onWriteable();
00365     break;
00366   case TCPSOCKET_CONTIMEOUT:
00367   case TCPSOCKET_CONRST:
00368   case TCPSOCKET_CONABRT:
00369   case TCPSOCKET_ERROR:
00370   case TCPSOCKET_DISCONNECTED:
00371     DBG("\r\nConnection error in handler\r\n");
00372     close();
00373     break;
00374   }
00375 }
00376 **/
00377 char* HTTPRequestHandler::getAddress(void)
00378 {
00379     return   m_pTCPSocketConnection->get_address();
00380 }
00381 
00382 string& HTTPRequestHandler::getRequestData(void)
00383 {
00384     return  m_reqData;
00385 }
00386