NetTribute library with debug turned on in FShandler Donatien Garner -> Segundo Equipo -> this version

Committer:
hexley
Date:
Fri Nov 19 01:54:45 2010 +0000
Revision:
0:281d6ff68967

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hexley 0:281d6ff68967 1
hexley 0:281d6ff68967 2 /*
hexley 0:281d6ff68967 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
hexley 0:281d6ff68967 4
hexley 0:281d6ff68967 5 Permission is hereby granted, free of charge, to any person obtaining a copy
hexley 0:281d6ff68967 6 of this software and associated documentation files (the "Software"), to deal
hexley 0:281d6ff68967 7 in the Software without restriction, including without limitation the rights
hexley 0:281d6ff68967 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
hexley 0:281d6ff68967 9 copies of the Software, and to permit persons to whom the Software is
hexley 0:281d6ff68967 10 furnished to do so, subject to the following conditions:
hexley 0:281d6ff68967 11
hexley 0:281d6ff68967 12 The above copyright notice and this permission notice shall be included in
hexley 0:281d6ff68967 13 all copies or substantial portions of the Software.
hexley 0:281d6ff68967 14
hexley 0:281d6ff68967 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
hexley 0:281d6ff68967 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
hexley 0:281d6ff68967 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
hexley 0:281d6ff68967 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
hexley 0:281d6ff68967 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
hexley 0:281d6ff68967 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
hexley 0:281d6ff68967 21 THE SOFTWARE.
hexley 0:281d6ff68967 22 */
hexley 0:281d6ff68967 23
hexley 0:281d6ff68967 24 #include "core/netservice.h"
hexley 0:281d6ff68967 25 #include "HTTPRequestHandler.h"
hexley 0:281d6ff68967 26
hexley 0:281d6ff68967 27 #include <string.h>
hexley 0:281d6ff68967 28
hexley 0:281d6ff68967 29 //#define __DEBUG
hexley 0:281d6ff68967 30 #include "dbg/dbg.h"
hexley 0:281d6ff68967 31
hexley 0:281d6ff68967 32 #define HTTP_REQUEST_TIMEOUT 5000
hexley 0:281d6ff68967 33
hexley 0:281d6ff68967 34 HTTPRequestHandler::HTTPRequestHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : NetService(),
hexley 0:281d6ff68967 35 m_pTCPSocket(pTCPSocket), m_reqHeaders(), m_respHeaders(),
hexley 0:281d6ff68967 36 m_rootPath(rootPath), m_path(path), m_errc(200),
hexley 0:281d6ff68967 37 m_watchdog(), m_timeout(0), m_closed(false), m_headersSent(false) //OK
hexley 0:281d6ff68967 38 {
hexley 0:281d6ff68967 39 //Read & parse headers
hexley 0:281d6ff68967 40 readHeaders();
hexley 0:281d6ff68967 41 m_pTCPSocket->setOnEvent(this, &HTTPRequestHandler::onTCPSocketEvent);
hexley 0:281d6ff68967 42 setTimeout(HTTP_REQUEST_TIMEOUT);
hexley 0:281d6ff68967 43 }
hexley 0:281d6ff68967 44
hexley 0:281d6ff68967 45 HTTPRequestHandler::~HTTPRequestHandler()
hexley 0:281d6ff68967 46 {
hexley 0:281d6ff68967 47 close();
hexley 0:281d6ff68967 48 }
hexley 0:281d6ff68967 49
hexley 0:281d6ff68967 50 void HTTPRequestHandler::onTimeout() //Connection has timed out
hexley 0:281d6ff68967 51 {
hexley 0:281d6ff68967 52 close();
hexley 0:281d6ff68967 53 }
hexley 0:281d6ff68967 54
hexley 0:281d6ff68967 55 void HTTPRequestHandler::close() //Close socket and destroy data
hexley 0:281d6ff68967 56 {
hexley 0:281d6ff68967 57 if(m_closed)
hexley 0:281d6ff68967 58 return;
hexley 0:281d6ff68967 59 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
hexley 0:281d6ff68967 60 m_watchdog.detach();
hexley 0:281d6ff68967 61 onClose();
hexley 0:281d6ff68967 62 m_pTCPSocket->resetOnEvent();
hexley 0:281d6ff68967 63 m_pTCPSocket->close();
hexley 0:281d6ff68967 64 delete m_pTCPSocket; //Can safely destroy socket
hexley 0:281d6ff68967 65 NetService::close();
hexley 0:281d6ff68967 66 }
hexley 0:281d6ff68967 67
hexley 0:281d6ff68967 68 map<string, string>& HTTPRequestHandler::reqHeaders() //const
hexley 0:281d6ff68967 69 {
hexley 0:281d6ff68967 70 return m_reqHeaders;
hexley 0:281d6ff68967 71 }
hexley 0:281d6ff68967 72
hexley 0:281d6ff68967 73 string& HTTPRequestHandler::path() //const
hexley 0:281d6ff68967 74 {
hexley 0:281d6ff68967 75 return m_path;
hexley 0:281d6ff68967 76 }
hexley 0:281d6ff68967 77
hexley 0:281d6ff68967 78 int HTTPRequestHandler::dataLen() const
hexley 0:281d6ff68967 79 {
hexley 0:281d6ff68967 80 map<string,string>::iterator it;
hexley 0:281d6ff68967 81 it = m_reqHeaders.find("Content-Length");
hexley 0:281d6ff68967 82 if( it == m_reqHeaders.end() )
hexley 0:281d6ff68967 83 {
hexley 0:281d6ff68967 84 return 0;
hexley 0:281d6ff68967 85 }
hexley 0:281d6ff68967 86 return atoi((*it).second.c_str()); //return 0 if parse fails, so that's fine
hexley 0:281d6ff68967 87 }
hexley 0:281d6ff68967 88
hexley 0:281d6ff68967 89 int HTTPRequestHandler::readData(char* buf, int len)
hexley 0:281d6ff68967 90 {
hexley 0:281d6ff68967 91 return m_pTCPSocket->recv(buf, len);
hexley 0:281d6ff68967 92 }
hexley 0:281d6ff68967 93
hexley 0:281d6ff68967 94 string& HTTPRequestHandler::rootPath() //const
hexley 0:281d6ff68967 95 {
hexley 0:281d6ff68967 96 return m_rootPath;
hexley 0:281d6ff68967 97 }
hexley 0:281d6ff68967 98
hexley 0:281d6ff68967 99 void HTTPRequestHandler::setErrCode(int errc)
hexley 0:281d6ff68967 100 {
hexley 0:281d6ff68967 101 m_errc = errc;
hexley 0:281d6ff68967 102 }
hexley 0:281d6ff68967 103
hexley 0:281d6ff68967 104 void HTTPRequestHandler::setContentLen(int len)
hexley 0:281d6ff68967 105 {
hexley 0:281d6ff68967 106 char len_str[6] = {0};
hexley 0:281d6ff68967 107 sprintf(len_str, "%d", len);
hexley 0:281d6ff68967 108 respHeaders()["Content-Length"] = len_str;
hexley 0:281d6ff68967 109 }
hexley 0:281d6ff68967 110
hexley 0:281d6ff68967 111 map<string, string>& HTTPRequestHandler::respHeaders()
hexley 0:281d6ff68967 112 {
hexley 0:281d6ff68967 113 return m_respHeaders;
hexley 0:281d6ff68967 114 }
hexley 0:281d6ff68967 115
hexley 0:281d6ff68967 116 int HTTPRequestHandler::writeData(const char* buf, int len)
hexley 0:281d6ff68967 117 {
hexley 0:281d6ff68967 118 if(!m_headersSent)
hexley 0:281d6ff68967 119 {
hexley 0:281d6ff68967 120 m_headersSent = true;
hexley 0:281d6ff68967 121 writeHeaders();
hexley 0:281d6ff68967 122 }
hexley 0:281d6ff68967 123
hexley 0:281d6ff68967 124 return m_pTCPSocket->send(buf, len);
hexley 0:281d6ff68967 125 }
hexley 0:281d6ff68967 126
hexley 0:281d6ff68967 127 void HTTPRequestHandler::setTimeout(int ms)
hexley 0:281d6ff68967 128 {
hexley 0:281d6ff68967 129 m_timeout = 1000*ms;
hexley 0:281d6ff68967 130 resetTimeout();
hexley 0:281d6ff68967 131 }
hexley 0:281d6ff68967 132
hexley 0:281d6ff68967 133 void HTTPRequestHandler::resetTimeout()
hexley 0:281d6ff68967 134 {
hexley 0:281d6ff68967 135 m_watchdog.detach();
hexley 0:281d6ff68967 136 m_watchdog.attach_us<HTTPRequestHandler>(this, &HTTPRequestHandler::onTimeout, m_timeout);
hexley 0:281d6ff68967 137 }
hexley 0:281d6ff68967 138
hexley 0:281d6ff68967 139
hexley 0:281d6ff68967 140 void HTTPRequestHandler::readHeaders()
hexley 0:281d6ff68967 141 {
hexley 0:281d6ff68967 142 static char line[128];
hexley 0:281d6ff68967 143 static char key[128];
hexley 0:281d6ff68967 144 static char value[128];
hexley 0:281d6ff68967 145 while( readLine(line, 128) > 0) //if == 0, it is an empty line = end of headers
hexley 0:281d6ff68967 146 {
hexley 0:281d6ff68967 147 int n = sscanf(line, "%[^:]: %[^\n]", key, value);
hexley 0:281d6ff68967 148 if ( n == 2 )
hexley 0:281d6ff68967 149 {
hexley 0:281d6ff68967 150 DBG("\r\nRead header : %s : %s\r\n", key, value);
hexley 0:281d6ff68967 151 m_reqHeaders[key] = value;
hexley 0:281d6ff68967 152 }
hexley 0:281d6ff68967 153 //TODO: Impl n==1 case (part 2 of previous header)
hexley 0:281d6ff68967 154 }
hexley 0:281d6ff68967 155 }
hexley 0:281d6ff68967 156
hexley 0:281d6ff68967 157 void HTTPRequestHandler::writeHeaders() //Called at the first writeData call
hexley 0:281d6ff68967 158 {
hexley 0:281d6ff68967 159 static char line[128];
hexley 0:281d6ff68967 160
hexley 0:281d6ff68967 161 //Response line
hexley 0:281d6ff68967 162 sprintf(line, "HTTP/1.1 %d MbedInfo\r\n", m_errc); //Not a violation of the standard not to include the descriptive text
hexley 0:281d6ff68967 163 m_pTCPSocket->send(line, strlen(line));
hexley 0:281d6ff68967 164
hexley 0:281d6ff68967 165 map<string,string>::iterator it;
hexley 0:281d6ff68967 166 while( !m_respHeaders.empty() )
hexley 0:281d6ff68967 167 {
hexley 0:281d6ff68967 168 it = m_respHeaders.begin();
hexley 0:281d6ff68967 169 sprintf(line, "%s: %s\r\n", (*it).first.c_str(), (*it).second.c_str() );
hexley 0:281d6ff68967 170 DBG("\r\n%s", line);
hexley 0:281d6ff68967 171 m_pTCPSocket->send(line, strlen(line));
hexley 0:281d6ff68967 172 m_respHeaders.erase(it);
hexley 0:281d6ff68967 173 }
hexley 0:281d6ff68967 174 m_pTCPSocket->send("\r\n",2); //End of head
hexley 0:281d6ff68967 175 }
hexley 0:281d6ff68967 176
hexley 0:281d6ff68967 177 int HTTPRequestHandler::readLine(char* str, int maxLen)
hexley 0:281d6ff68967 178 {
hexley 0:281d6ff68967 179 int ret;
hexley 0:281d6ff68967 180 int len = 0;
hexley 0:281d6ff68967 181 for(int i = 0; i < maxLen - 1; i++)
hexley 0:281d6ff68967 182 {
hexley 0:281d6ff68967 183 ret = m_pTCPSocket->recv(str, 1);
hexley 0:281d6ff68967 184 if(!ret)
hexley 0:281d6ff68967 185 {
hexley 0:281d6ff68967 186 break;
hexley 0:281d6ff68967 187 }
hexley 0:281d6ff68967 188 if( (len > 1) && *(str-1)=='\r' && *str=='\n' )
hexley 0:281d6ff68967 189 {
hexley 0:281d6ff68967 190 str--;
hexley 0:281d6ff68967 191 len-=2;
hexley 0:281d6ff68967 192 break;
hexley 0:281d6ff68967 193 }
hexley 0:281d6ff68967 194 else if( *str=='\n' )
hexley 0:281d6ff68967 195 {
hexley 0:281d6ff68967 196 len--;
hexley 0:281d6ff68967 197 break;
hexley 0:281d6ff68967 198 }
hexley 0:281d6ff68967 199 str++;
hexley 0:281d6ff68967 200 len++;
hexley 0:281d6ff68967 201 }
hexley 0:281d6ff68967 202 *str = 0;
hexley 0:281d6ff68967 203 return len;
hexley 0:281d6ff68967 204 }
hexley 0:281d6ff68967 205
hexley 0:281d6ff68967 206 void HTTPRequestHandler::onTCPSocketEvent(TCPSocketEvent e)
hexley 0:281d6ff68967 207 {
hexley 0:281d6ff68967 208
hexley 0:281d6ff68967 209 DBG("\r\nEvent %d in HTTPRequestHandler\r\n", e);
hexley 0:281d6ff68967 210
hexley 0:281d6ff68967 211 if(m_closed)
hexley 0:281d6ff68967 212 {
hexley 0:281d6ff68967 213 DBG("\r\nWARN: Discarded\r\n");
hexley 0:281d6ff68967 214 return;
hexley 0:281d6ff68967 215 }
hexley 0:281d6ff68967 216
hexley 0:281d6ff68967 217 switch(e)
hexley 0:281d6ff68967 218 {
hexley 0:281d6ff68967 219 case TCPSOCKET_READABLE:
hexley 0:281d6ff68967 220 resetTimeout();
hexley 0:281d6ff68967 221 onReadable();
hexley 0:281d6ff68967 222 break;
hexley 0:281d6ff68967 223 case TCPSOCKET_WRITEABLE:
hexley 0:281d6ff68967 224 resetTimeout();
hexley 0:281d6ff68967 225 onWriteable();
hexley 0:281d6ff68967 226 break;
hexley 0:281d6ff68967 227 case TCPSOCKET_CONTIMEOUT:
hexley 0:281d6ff68967 228 case TCPSOCKET_CONRST:
hexley 0:281d6ff68967 229 case TCPSOCKET_CONABRT:
hexley 0:281d6ff68967 230 case TCPSOCKET_ERROR:
hexley 0:281d6ff68967 231 case TCPSOCKET_DISCONNECTED:
hexley 0:281d6ff68967 232 DBG("\r\nConnection error in handler\r\n");
hexley 0:281d6ff68967 233 close();
hexley 0:281d6ff68967 234 break;
hexley 0:281d6ff68967 235 }
hexley 0:281d6ff68967 236
hexley 0:281d6ff68967 237 }