WIZ820io(W5200) network interface、EthernetNetIf compatible.

/media/uploads/va009039/wiz820ionetif.jpg

example

#include "WIZ820ioNetIf.h"
#include "HTTPClient.h"
#include "HTTPServer.h"

#if defined(TARGET_KL25Z)
WIZ820ioNetIf eth(PTD2,PTD3,PTD1,PTD0,PTD5);
#endif
HTTPClient http;
HTTPStream stream;

void callback(HTTPResult r){
    printf("callback %d %s\n", r, HTTPClient::ResultStr(r));
}

int main() {
    int err = eth.setup();
    if (err < 0) {
        printf("setup error %d\n", err);
        exit(-1);
    }    

    HTTPServer svr;
    svr.addHandler<SimpleHandler>("/");
    svr.bind(80);

    const char* uri = "http://va009039-mbed.appspot.com/kl25z/";
    http.get(uri, &stream, callback);
    uint8_t buf[256];
    int total = 0;
    stream.readNext(buf, sizeof(buf));
    while(1) {
        if(stream.readable()) {
            int len = stream.readLen();
            total += len;
            printf("%d %d\n", total, len);
            stream.readNext(buf, sizeof(buf));
        }
        Net::poll();
    }
}
Committer:
va009039
Date:
Sun Mar 24 11:25:31 2013 +0000
Revision:
1:22b9052d864d
WIZ820io(W8200) ethernet interface, EthernetNetIf compatible.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 1:22b9052d864d 1
va009039 1:22b9052d864d 2 /*
va009039 1:22b9052d864d 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
va009039 1:22b9052d864d 4
va009039 1:22b9052d864d 5 Permission is hereby granted, free of charge, to any person obtaining a copy
va009039 1:22b9052d864d 6 of this software and associated documentation files (the "Software"), to deal
va009039 1:22b9052d864d 7 in the Software without restriction, including without limitation the rights
va009039 1:22b9052d864d 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
va009039 1:22b9052d864d 9 copies of the Software, and to permit persons to whom the Software is
va009039 1:22b9052d864d 10 furnished to do so, subject to the following conditions:
va009039 1:22b9052d864d 11
va009039 1:22b9052d864d 12 The above copyright notice and this permission notice shall be included in
va009039 1:22b9052d864d 13 all copies or substantial portions of the Software.
va009039 1:22b9052d864d 14
va009039 1:22b9052d864d 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
va009039 1:22b9052d864d 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
va009039 1:22b9052d864d 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
va009039 1:22b9052d864d 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
va009039 1:22b9052d864d 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
va009039 1:22b9052d864d 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
va009039 1:22b9052d864d 21 THE SOFTWARE.
va009039 1:22b9052d864d 22 */
va009039 1:22b9052d864d 23
va009039 1:22b9052d864d 24 #include "core/netservice.h"
va009039 1:22b9052d864d 25 #include "HTTPClient.h"
va009039 1:22b9052d864d 26 #include "../util/base64.h"
va009039 1:22b9052d864d 27 #include "../util/url.h"
va009039 1:22b9052d864d 28
va009039 1:22b9052d864d 29 //#define __DEBUG
va009039 1:22b9052d864d 30 //#include "dbg/dbg.h"
va009039 1:22b9052d864d 31 //#define DEBUG
va009039 1:22b9052d864d 32 #include "w5200debug.h"
va009039 1:22b9052d864d 33
va009039 1:22b9052d864d 34 #define HTTP_REQUEST_TIMEOUT 30000//15000
va009039 1:22b9052d864d 35 #define HTTP_PORT 80
va009039 1:22b9052d864d 36
va009039 1:22b9052d864d 37 #define CHUNK_SIZE 256
va009039 1:22b9052d864d 38
va009039 1:22b9052d864d 39 HTTPClient::HTTPClient() : NetService(false) /*Not owned by the pool*/, m_meth(HTTP_GET), m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL),
va009039 1:22b9052d864d 40 m_watchdog(), m_timeout(0), m_pDnsReq(NULL), m_server(), m_path(),
va009039 1:22b9052d864d 41 m_closed(true), m_state(HTTP_CLOSED),
va009039 1:22b9052d864d 42 m_pDataOut(NULL), m_pDataIn(NULL), m_dataChunked(false), m_dataPos(0), m_dataLen(0), m_httpResponseCode(0), m_blockingResult(HTTP_PROCESSING)
va009039 1:22b9052d864d 43
va009039 1:22b9052d864d 44 {
va009039 1:22b9052d864d 45 setTimeout(HTTP_REQUEST_TIMEOUT);
va009039 1:22b9052d864d 46 m_buf = new char[CHUNK_SIZE];
va009039 1:22b9052d864d 47 DBG("New HTTPClient %p\n",this);
va009039 1:22b9052d864d 48 }
va009039 1:22b9052d864d 49
va009039 1:22b9052d864d 50 HTTPClient::~HTTPClient()
va009039 1:22b9052d864d 51 {
va009039 1:22b9052d864d 52 close();
va009039 1:22b9052d864d 53 delete[] m_buf;
va009039 1:22b9052d864d 54 }
va009039 1:22b9052d864d 55
va009039 1:22b9052d864d 56 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
va009039 1:22b9052d864d 57 {
va009039 1:22b9052d864d 58 if(user==NULL)
va009039 1:22b9052d864d 59 {
va009039 1:22b9052d864d 60 m_reqHeaders.erase("Authorization"); //Remove auth str
va009039 1:22b9052d864d 61 return;
va009039 1:22b9052d864d 62 }
va009039 1:22b9052d864d 63 string auth = "Basic ";
va009039 1:22b9052d864d 64 string decStr = user;
va009039 1:22b9052d864d 65 decStr += ":";
va009039 1:22b9052d864d 66 decStr += password;
va009039 1:22b9052d864d 67 auth.append( Base64::encode(decStr) );
va009039 1:22b9052d864d 68 DBG("Auth str is %s\n", auth.c_str());
va009039 1:22b9052d864d 69 m_reqHeaders["Authorization"] = auth;
va009039 1:22b9052d864d 70 }
va009039 1:22b9052d864d 71
va009039 1:22b9052d864d 72 //High Level setup functions
va009039 1:22b9052d864d 73 HTTPResult HTTPClient::get(const char* uri, HTTPData* pDataIn) //Blocking
va009039 1:22b9052d864d 74 {
va009039 1:22b9052d864d 75 doGet(uri, pDataIn);
va009039 1:22b9052d864d 76 return blockingProcess();
va009039 1:22b9052d864d 77 }
va009039 1:22b9052d864d 78
va009039 1:22b9052d864d 79 HTTPResult HTTPClient::get(const char* uri, HTTPData* pDataIn, void (*pMethod)(HTTPResult)) //Non blocking
va009039 1:22b9052d864d 80 {
va009039 1:22b9052d864d 81 setOnResult(pMethod);
va009039 1:22b9052d864d 82 doGet(uri, pDataIn);
va009039 1:22b9052d864d 83 return HTTP_PROCESSING;
va009039 1:22b9052d864d 84 }
va009039 1:22b9052d864d 85
va009039 1:22b9052d864d 86 #if 0 //For info only
va009039 1:22b9052d864d 87 template<class T>
va009039 1:22b9052d864d 88 HTTPResult HTTPClient::get(const char* uri, HTTPData* pDataIn, T* pItem, void (T::*pMethod)(HTTPResult)) //Non blocking
va009039 1:22b9052d864d 89 {
va009039 1:22b9052d864d 90 setOnResult(pItem, pMethod);
va009039 1:22b9052d864d 91 doGet(uri, pDataIn);
va009039 1:22b9052d864d 92 return HTTP_PROCESSING;
va009039 1:22b9052d864d 93 }
va009039 1:22b9052d864d 94 #endif
va009039 1:22b9052d864d 95
va009039 1:22b9052d864d 96 HTTPResult HTTPClient::post(const char* uri, const HTTPData& dataOut, HTTPData* pDataIn) //Blocking
va009039 1:22b9052d864d 97 {
va009039 1:22b9052d864d 98 doPost(uri, dataOut, pDataIn);
va009039 1:22b9052d864d 99 return blockingProcess();
va009039 1:22b9052d864d 100 }
va009039 1:22b9052d864d 101
va009039 1:22b9052d864d 102 HTTPResult HTTPClient::post(const char* uri, const HTTPData& dataOut, HTTPData* pDataIn, void (*pMethod)(HTTPResult)) //Non blocking
va009039 1:22b9052d864d 103 {
va009039 1:22b9052d864d 104 setOnResult(pMethod);
va009039 1:22b9052d864d 105 doPost(uri, dataOut, pDataIn);
va009039 1:22b9052d864d 106 return HTTP_PROCESSING;
va009039 1:22b9052d864d 107 }
va009039 1:22b9052d864d 108
va009039 1:22b9052d864d 109 #if 0 //For info only
va009039 1:22b9052d864d 110 template<class T>
va009039 1:22b9052d864d 111 HTTPResult HTTPClient::post(const char* uri, const HTTPData& dataOut, HTTPData* pDataIn, T* pItem, void (T::*pMethod)(HTTPResult)) //Non blocking
va009039 1:22b9052d864d 112 {
va009039 1:22b9052d864d 113 setOnResult(pItem, pMethod);
va009039 1:22b9052d864d 114 doPost(uri, dataOut, pDataIn);
va009039 1:22b9052d864d 115 return HTTP_PROCESSING;
va009039 1:22b9052d864d 116 }
va009039 1:22b9052d864d 117 #endif
va009039 1:22b9052d864d 118
va009039 1:22b9052d864d 119 void HTTPClient::doGet(const char* uri, HTTPData* pDataIn)
va009039 1:22b9052d864d 120 {
va009039 1:22b9052d864d 121 m_meth = HTTP_GET;
va009039 1:22b9052d864d 122 setup(uri, NULL, pDataIn);
va009039 1:22b9052d864d 123 }
va009039 1:22b9052d864d 124
va009039 1:22b9052d864d 125 void HTTPClient::doPost(const char* uri, const HTTPData& dataOut, HTTPData* pDataIn)
va009039 1:22b9052d864d 126 {
va009039 1:22b9052d864d 127 m_meth = HTTP_POST;
va009039 1:22b9052d864d 128 setup(uri, (HTTPData*) &dataOut, pDataIn);
va009039 1:22b9052d864d 129 }
va009039 1:22b9052d864d 130
va009039 1:22b9052d864d 131 void HTTPClient::setOnResult( void (*pMethod)(HTTPResult) )
va009039 1:22b9052d864d 132 {
va009039 1:22b9052d864d 133 m_pCb = pMethod;
va009039 1:22b9052d864d 134 m_pCbItem = NULL;
va009039 1:22b9052d864d 135 m_pCbMeth = NULL;
va009039 1:22b9052d864d 136 }
va009039 1:22b9052d864d 137
va009039 1:22b9052d864d 138 #if 0 //For info only
va009039 1:22b9052d864d 139 template<class T>
va009039 1:22b9052d864d 140 void HTTPClient::setOnResult( T* pItem, void (T::*pMethod)(NtpResult) )
va009039 1:22b9052d864d 141 {
va009039 1:22b9052d864d 142 m_pCb = NULL;
va009039 1:22b9052d864d 143 m_pCbItem = (CDummy*) pItem;
va009039 1:22b9052d864d 144 m_pCbMeth = (void (CDummy::*)(NtpResult)) pMethod;
va009039 1:22b9052d864d 145 }
va009039 1:22b9052d864d 146 #endif
va009039 1:22b9052d864d 147
va009039 1:22b9052d864d 148 void HTTPClient::setTimeout(int ms)
va009039 1:22b9052d864d 149 {
va009039 1:22b9052d864d 150 m_timeout = ms;
va009039 1:22b9052d864d 151 //resetTimeout();
va009039 1:22b9052d864d 152 }
va009039 1:22b9052d864d 153
va009039 1:22b9052d864d 154 void HTTPClient::poll() //Called by NetServices
va009039 1:22b9052d864d 155 {
va009039 1:22b9052d864d 156 if(m_closed)
va009039 1:22b9052d864d 157 {
va009039 1:22b9052d864d 158 return;
va009039 1:22b9052d864d 159 }
va009039 1:22b9052d864d 160 if(m_watchdog.read_ms()>m_timeout)
va009039 1:22b9052d864d 161 {
va009039 1:22b9052d864d 162 onTimeout();
va009039 1:22b9052d864d 163 }
va009039 1:22b9052d864d 164 else if(m_state == HTTP_READ_DATA_INCOMPLETE)
va009039 1:22b9052d864d 165 {
va009039 1:22b9052d864d 166 readData(); //Try to read more data
va009039 1:22b9052d864d 167 if( m_state == HTTP_DONE )
va009039 1:22b9052d864d 168 {
va009039 1:22b9052d864d 169 //All data has been read, close w/ success :)
va009039 1:22b9052d864d 170 DBG("Done :)!\n");
va009039 1:22b9052d864d 171 onResult(HTTP_OK);
va009039 1:22b9052d864d 172 close();
va009039 1:22b9052d864d 173 }
va009039 1:22b9052d864d 174 }
va009039 1:22b9052d864d 175
va009039 1:22b9052d864d 176 }
va009039 1:22b9052d864d 177
va009039 1:22b9052d864d 178 int HTTPClient::getHTTPResponseCode()
va009039 1:22b9052d864d 179 {
va009039 1:22b9052d864d 180 return m_httpResponseCode;
va009039 1:22b9052d864d 181 }
va009039 1:22b9052d864d 182
va009039 1:22b9052d864d 183 void HTTPClient::setRequestHeader(const string& header, const string& value)
va009039 1:22b9052d864d 184 {
va009039 1:22b9052d864d 185 m_reqHeaders[header] = value;
va009039 1:22b9052d864d 186 }
va009039 1:22b9052d864d 187
va009039 1:22b9052d864d 188 string& HTTPClient::getResponseHeader(const string& header)
va009039 1:22b9052d864d 189 {
va009039 1:22b9052d864d 190 return m_respHeaders[header];
va009039 1:22b9052d864d 191 }
va009039 1:22b9052d864d 192
va009039 1:22b9052d864d 193 void HTTPClient::resetRequestHeaders()
va009039 1:22b9052d864d 194 {
va009039 1:22b9052d864d 195 m_reqHeaders.clear();
va009039 1:22b9052d864d 196 }
va009039 1:22b9052d864d 197
va009039 1:22b9052d864d 198 void HTTPClient::resetTimeout()
va009039 1:22b9052d864d 199 {
va009039 1:22b9052d864d 200 m_watchdog.reset();
va009039 1:22b9052d864d 201 m_watchdog.start();
va009039 1:22b9052d864d 202 }
va009039 1:22b9052d864d 203
va009039 1:22b9052d864d 204 void HTTPClient::init() //Create and setup socket if needed
va009039 1:22b9052d864d 205 {
va009039 1:22b9052d864d 206 close(); //Remove previous elements
va009039 1:22b9052d864d 207 if(!m_closed) //Already opened
va009039 1:22b9052d864d 208 return;
va009039 1:22b9052d864d 209 m_state = HTTP_WRITE_HEADERS;
va009039 1:22b9052d864d 210 m_pTCPSocket = new TCPSocket;
va009039 1:22b9052d864d 211 m_pTCPSocket->setOnEvent(this, &HTTPClient::onTCPSocketEvent);
va009039 1:22b9052d864d 212 m_closed = false;
va009039 1:22b9052d864d 213 m_httpResponseCode = 0;
va009039 1:22b9052d864d 214 }
va009039 1:22b9052d864d 215
va009039 1:22b9052d864d 216 void HTTPClient::close()
va009039 1:22b9052d864d 217 {
va009039 1:22b9052d864d 218 if(m_closed)
va009039 1:22b9052d864d 219 return;
va009039 1:22b9052d864d 220 m_state = HTTP_CLOSED;
va009039 1:22b9052d864d 221 //Now Request headers are kept btw requests unless resetRequestHeaders() is called
va009039 1:22b9052d864d 222 //m_reqHeaders.clear(); //Clear headers for next requests
va009039 1:22b9052d864d 223 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
va009039 1:22b9052d864d 224 m_watchdog.stop(); //Stop timeout
va009039 1:22b9052d864d 225 m_watchdog.reset();
va009039 1:22b9052d864d 226 m_pTCPSocket->resetOnEvent();
va009039 1:22b9052d864d 227 m_pTCPSocket->close();
va009039 1:22b9052d864d 228 delete m_pTCPSocket;
va009039 1:22b9052d864d 229 m_pTCPSocket = NULL;
va009039 1:22b9052d864d 230 if( m_pDnsReq )
va009039 1:22b9052d864d 231 {
va009039 1:22b9052d864d 232 m_pDnsReq->close();
va009039 1:22b9052d864d 233 delete m_pDnsReq;
va009039 1:22b9052d864d 234 m_pDnsReq = NULL;
va009039 1:22b9052d864d 235 }
va009039 1:22b9052d864d 236 }
va009039 1:22b9052d864d 237
va009039 1:22b9052d864d 238 void HTTPClient::setup(const char* uri, HTTPData* pDataOut, HTTPData* pDataIn) //Setup request, make DNS Req if necessary
va009039 1:22b9052d864d 239 {
va009039 1:22b9052d864d 240 init(); //Initialize client in known state, create socket
va009039 1:22b9052d864d 241 m_pDataOut = pDataOut;
va009039 1:22b9052d864d 242 m_pDataIn = pDataIn;
va009039 1:22b9052d864d 243 resetTimeout();
va009039 1:22b9052d864d 244
va009039 1:22b9052d864d 245 //Erase previous headers
va009039 1:22b9052d864d 246 //Do NOT clear m_reqHeaders as they might have already set before connecting
va009039 1:22b9052d864d 247 m_respHeaders.clear();
va009039 1:22b9052d864d 248
va009039 1:22b9052d864d 249 //Erase response buffer
va009039 1:22b9052d864d 250 if(m_pDataIn)
va009039 1:22b9052d864d 251 m_pDataIn->clear();
va009039 1:22b9052d864d 252
va009039 1:22b9052d864d 253 //Assert that buffers are initialized properly
va009039 1:22b9052d864d 254 m_dataLen = 0;
va009039 1:22b9052d864d 255 m_bufRemainingLen = 0;
va009039 1:22b9052d864d 256
va009039 1:22b9052d864d 257 Url url;
va009039 1:22b9052d864d 258 url.fromString(uri);
va009039 1:22b9052d864d 259
va009039 1:22b9052d864d 260 m_path = url.getPath();
va009039 1:22b9052d864d 261
va009039 1:22b9052d864d 262 m_server.setName(url.getHost().c_str());
va009039 1:22b9052d864d 263
va009039 1:22b9052d864d 264 if( url.getPort() > 0 )
va009039 1:22b9052d864d 265 {
va009039 1:22b9052d864d 266 m_server.setPort( url.getPort() );
va009039 1:22b9052d864d 267 }
va009039 1:22b9052d864d 268 else
va009039 1:22b9052d864d 269 {
va009039 1:22b9052d864d 270 m_server.setPort( HTTP_PORT );
va009039 1:22b9052d864d 271 }
va009039 1:22b9052d864d 272
va009039 1:22b9052d864d 273 DBG("URL parsed,\r\nHost: %s\r\nPort: %d\r\nPath: %s\n", url.getHost().c_str(), url.getPort(), url.getPath().c_str());
va009039 1:22b9052d864d 274
va009039 1:22b9052d864d 275 IpAddr ip;
va009039 1:22b9052d864d 276 if( url.getHostIp(&ip) )
va009039 1:22b9052d864d 277 {
va009039 1:22b9052d864d 278 m_server.setIp(ip);
va009039 1:22b9052d864d 279 connect();
va009039 1:22b9052d864d 280 }
va009039 1:22b9052d864d 281 else
va009039 1:22b9052d864d 282 {
va009039 1:22b9052d864d 283 DBG("DNS Query...\n");
va009039 1:22b9052d864d 284 m_pDnsReq = new DNSRequest();
va009039 1:22b9052d864d 285 m_pDnsReq->setOnReply(this, &HTTPClient::onDNSReply);
va009039 1:22b9052d864d 286 m_pDnsReq->resolve(&m_server);
va009039 1:22b9052d864d 287 DBG("HTTPClient : DNSRequest %p\n", m_pDnsReq);
va009039 1:22b9052d864d 288 }
va009039 1:22b9052d864d 289
va009039 1:22b9052d864d 290 }
va009039 1:22b9052d864d 291
va009039 1:22b9052d864d 292 void HTTPClient::connect() //Start Connection
va009039 1:22b9052d864d 293 {
va009039 1:22b9052d864d 294 resetTimeout();
va009039 1:22b9052d864d 295 DBG("Connecting...\n");
va009039 1:22b9052d864d 296 m_pTCPSocket->connect(m_server);
va009039 1:22b9052d864d 297 }
va009039 1:22b9052d864d 298
va009039 1:22b9052d864d 299 #define MIN(a,b) ((a)<(b)?(a):(b))
va009039 1:22b9052d864d 300 #define ABS(a) (((a)>0)?(a):0)
va009039 1:22b9052d864d 301 int HTTPClient::tryRead() //Try to read data from tcp packet and put in the HTTPData object
va009039 1:22b9052d864d 302 {
va009039 1:22b9052d864d 303 int len = 0;
va009039 1:22b9052d864d 304 int readLen;
va009039 1:22b9052d864d 305 do
va009039 1:22b9052d864d 306 {
va009039 1:22b9052d864d 307 if(m_state == HTTP_READ_DATA_INCOMPLETE) //First try to complete buffer copy
va009039 1:22b9052d864d 308 {
va009039 1:22b9052d864d 309 readLen = m_bufRemainingLen;
va009039 1:22b9052d864d 310 /* if (readLen == 0)
va009039 1:22b9052d864d 311 {
va009039 1:22b9052d864d 312 m_state = HTTP_READ_DATA;
va009039 1:22b9052d864d 313 continue;
va009039 1:22b9052d864d 314 }*/
va009039 1:22b9052d864d 315 }
va009039 1:22b9052d864d 316 else
va009039 1:22b9052d864d 317 {
va009039 1:22b9052d864d 318 readLen = m_pTCPSocket->recv(m_buf, MIN(ABS(m_dataLen-m_dataPos),CHUNK_SIZE));
va009039 1:22b9052d864d 319 if(readLen < 0) //Error
va009039 1:22b9052d864d 320 {
va009039 1:22b9052d864d 321 return readLen;
va009039 1:22b9052d864d 322 }
va009039 1:22b9052d864d 323
va009039 1:22b9052d864d 324 DBG("%d bytes read\n", readLen);
va009039 1:22b9052d864d 325
va009039 1:22b9052d864d 326 m_pBufRemaining = m_buf;
va009039 1:22b9052d864d 327 }
va009039 1:22b9052d864d 328 if (readLen == 0)
va009039 1:22b9052d864d 329 {
va009039 1:22b9052d864d 330 m_state = HTTP_READ_DATA;
va009039 1:22b9052d864d 331 return len;
va009039 1:22b9052d864d 332 }
va009039 1:22b9052d864d 333
va009039 1:22b9052d864d 334 DBG("Trying to write %d bytes\n", readLen);
va009039 1:22b9052d864d 335
va009039 1:22b9052d864d 336 int writtenLen = m_pDataIn->write(m_pBufRemaining, readLen);
va009039 1:22b9052d864d 337 m_dataPos += writtenLen;
va009039 1:22b9052d864d 338
va009039 1:22b9052d864d 339 DBG("%d bytes written\n", writtenLen);
va009039 1:22b9052d864d 340
va009039 1:22b9052d864d 341 if(writtenLen<readLen) //Data was not completely written
va009039 1:22b9052d864d 342 {
va009039 1:22b9052d864d 343 m_pBufRemaining += writtenLen;
va009039 1:22b9052d864d 344 m_bufRemainingLen = readLen - writtenLen;
va009039 1:22b9052d864d 345 m_state = HTTP_READ_DATA_INCOMPLETE;
va009039 1:22b9052d864d 346 return len + writtenLen;
va009039 1:22b9052d864d 347 }
va009039 1:22b9052d864d 348 else
va009039 1:22b9052d864d 349 {
va009039 1:22b9052d864d 350 m_state = HTTP_READ_DATA;
va009039 1:22b9052d864d 351 }
va009039 1:22b9052d864d 352 len += readLen;
va009039 1:22b9052d864d 353 } while(readLen>0);
va009039 1:22b9052d864d 354
va009039 1:22b9052d864d 355 return len;
va009039 1:22b9052d864d 356 }
va009039 1:22b9052d864d 357
va009039 1:22b9052d864d 358 void HTTPClient::readData() //Data has been read
va009039 1:22b9052d864d 359 {
va009039 1:22b9052d864d 360 if(m_pDataIn == NULL) //Nothing to read (in HEAD for instance, not supported now)
va009039 1:22b9052d864d 361 {
va009039 1:22b9052d864d 362 m_state = HTTP_DONE;
va009039 1:22b9052d864d 363 return;
va009039 1:22b9052d864d 364 }
va009039 1:22b9052d864d 365 DBG("Reading response...\n");
va009039 1:22b9052d864d 366 int len = 0;
va009039 1:22b9052d864d 367 do
va009039 1:22b9052d864d 368 {
va009039 1:22b9052d864d 369 if(m_dataChunked && (m_state != HTTP_READ_DATA_INCOMPLETE))
va009039 1:22b9052d864d 370 {
va009039 1:22b9052d864d 371 if(m_dataLen==0)
va009039 1:22b9052d864d 372 {
va009039 1:22b9052d864d 373 DBG("Reading chunk length...\n");
va009039 1:22b9052d864d 374 //New block
va009039 1:22b9052d864d 375 static char chunkHeader[16];
va009039 1:22b9052d864d 376 //We use m_dataPos to retain the read position in chunkHeader, it has been set to 0 before the first call of readData()
va009039 1:22b9052d864d 377 m_dataPos += readLine(chunkHeader + m_dataPos, ABS(16 - m_dataPos));
va009039 1:22b9052d864d 378 if( m_dataPos > 0 )
va009039 1:22b9052d864d 379 {
va009039 1:22b9052d864d 380 if( chunkHeader[strlen(chunkHeader)-1] == 0x0d )
va009039 1:22b9052d864d 381 {
va009039 1:22b9052d864d 382 sscanf(chunkHeader, "%x%*[^\r\n]", &m_dataLen);
va009039 1:22b9052d864d 383 DBG("Chunk length is %d\n", m_dataLen);
va009039 1:22b9052d864d 384 m_dataPos = 0;
va009039 1:22b9052d864d 385 }
va009039 1:22b9052d864d 386 else
va009039 1:22b9052d864d 387 {
va009039 1:22b9052d864d 388 //Wait for end of line
va009039 1:22b9052d864d 389 DBG("Wait for CRLF\n");
va009039 1:22b9052d864d 390 return;
va009039 1:22b9052d864d 391 }
va009039 1:22b9052d864d 392 }
va009039 1:22b9052d864d 393 else
va009039 1:22b9052d864d 394 {
va009039 1:22b9052d864d 395 DBG("Wait for data\n");
va009039 1:22b9052d864d 396 //Wait for data
va009039 1:22b9052d864d 397 return;
va009039 1:22b9052d864d 398 }
va009039 1:22b9052d864d 399 }
va009039 1:22b9052d864d 400 }
va009039 1:22b9052d864d 401
va009039 1:22b9052d864d 402 //Proper data recovery
va009039 1:22b9052d864d 403 len = tryRead();
va009039 1:22b9052d864d 404 if(len<0) //Error
va009039 1:22b9052d864d 405 {
va009039 1:22b9052d864d 406 onResult(HTTP_CONN);
va009039 1:22b9052d864d 407 return;
va009039 1:22b9052d864d 408 }
va009039 1:22b9052d864d 409
va009039 1:22b9052d864d 410 if(len>0)
va009039 1:22b9052d864d 411 resetTimeout();
va009039 1:22b9052d864d 412
va009039 1:22b9052d864d 413 if(m_state == HTTP_READ_DATA_INCOMPLETE)
va009039 1:22b9052d864d 414 return;
va009039 1:22b9052d864d 415
va009039 1:22b9052d864d 416 //Chunk Tail
va009039 1:22b9052d864d 417 if(m_dataChunked)
va009039 1:22b9052d864d 418 {
va009039 1:22b9052d864d 419 if(m_dataPos >= m_dataLen)
va009039 1:22b9052d864d 420 {
va009039 1:22b9052d864d 421 DBG("Chunk read, wait for CRLF\n");
va009039 1:22b9052d864d 422 char chunkTail[3];
va009039 1:22b9052d864d 423 m_dataPos += readLine(chunkTail, 3);
va009039 1:22b9052d864d 424 }
va009039 1:22b9052d864d 425
va009039 1:22b9052d864d 426 if(m_dataPos >= m_dataLen + 1) //1 == strlen("\n"),
va009039 1:22b9052d864d 427 {
va009039 1:22b9052d864d 428 DBG("End of chunk\n");
va009039 1:22b9052d864d 429 if(m_dataLen==0)
va009039 1:22b9052d864d 430 {
va009039 1:22b9052d864d 431 DBG("End of file\n");
va009039 1:22b9052d864d 432 //End of file
va009039 1:22b9052d864d 433 m_state = HTTP_DONE; //Done
va009039 1:22b9052d864d 434 }
va009039 1:22b9052d864d 435 m_dataLen = 0;
va009039 1:22b9052d864d 436 m_dataPos = 0;
va009039 1:22b9052d864d 437 }
va009039 1:22b9052d864d 438 }
va009039 1:22b9052d864d 439
va009039 1:22b9052d864d 440 } while(len>0);
va009039 1:22b9052d864d 441
va009039 1:22b9052d864d 442
va009039 1:22b9052d864d 443 if(!m_dataChunked && (m_dataPos >= m_dataLen)) //All Data has been received
va009039 1:22b9052d864d 444 {
va009039 1:22b9052d864d 445 DBG("End of file\n");
va009039 1:22b9052d864d 446 m_state = HTTP_DONE; //Done
va009039 1:22b9052d864d 447 }
va009039 1:22b9052d864d 448 }
va009039 1:22b9052d864d 449
va009039 1:22b9052d864d 450 void HTTPClient::writeData() //Data has been written & buf is free
va009039 1:22b9052d864d 451 {
va009039 1:22b9052d864d 452 if(m_pDataOut == NULL) //Nothing to write (in POST for instance)
va009039 1:22b9052d864d 453 {
va009039 1:22b9052d864d 454 m_dataLen = 0; //Reset Data Length
va009039 1:22b9052d864d 455 m_state = HTTP_READ_HEADERS;
va009039 1:22b9052d864d 456 return;
va009039 1:22b9052d864d 457 }
va009039 1:22b9052d864d 458 int len = m_pDataOut->read(m_buf, CHUNK_SIZE);
va009039 1:22b9052d864d 459 if( m_dataChunked )
va009039 1:22b9052d864d 460 {
va009039 1:22b9052d864d 461 //Write chunk header
va009039 1:22b9052d864d 462 char chunkHeader[16];
va009039 1:22b9052d864d 463 sprintf(chunkHeader, "%d\r\n", len);
va009039 1:22b9052d864d 464 int ret = m_pTCPSocket->send(chunkHeader, strlen(chunkHeader));
va009039 1:22b9052d864d 465 if(ret < 0)//Error
va009039 1:22b9052d864d 466 {
va009039 1:22b9052d864d 467 onResult(HTTP_CONN);
va009039 1:22b9052d864d 468 return;
va009039 1:22b9052d864d 469 }
va009039 1:22b9052d864d 470 }
va009039 1:22b9052d864d 471 m_pTCPSocket->send(m_buf, len);
va009039 1:22b9052d864d 472 m_dataPos+=len;
va009039 1:22b9052d864d 473 if( m_dataChunked )
va009039 1:22b9052d864d 474 {
va009039 1:22b9052d864d 475 m_pTCPSocket->send("\r\n", 2); //Chunk-terminating CRLF
va009039 1:22b9052d864d 476 }
va009039 1:22b9052d864d 477 if( ( !m_dataChunked && (m_dataPos >= m_dataLen) )
va009039 1:22b9052d864d 478 || ( m_dataChunked && !len ) ) //All Data has been sent
va009039 1:22b9052d864d 479 {
va009039 1:22b9052d864d 480 m_dataLen = 0; //Reset Data Length
va009039 1:22b9052d864d 481 m_state = HTTP_READ_HEADERS; //Wait for resp
va009039 1:22b9052d864d 482 }
va009039 1:22b9052d864d 483 }
va009039 1:22b9052d864d 484
va009039 1:22b9052d864d 485 void HTTPClient::onTCPSocketEvent(TCPSocketEvent e)
va009039 1:22b9052d864d 486 {
va009039 1:22b9052d864d 487 DBG("Event %d in HTTPClient::onTCPSocketEvent()\n", e);
va009039 1:22b9052d864d 488
va009039 1:22b9052d864d 489 if(m_closed)
va009039 1:22b9052d864d 490 {
va009039 1:22b9052d864d 491 DBG("WARN: Discarded\n");
va009039 1:22b9052d864d 492 return;
va009039 1:22b9052d864d 493 }
va009039 1:22b9052d864d 494
va009039 1:22b9052d864d 495 switch(e)
va009039 1:22b9052d864d 496 {
va009039 1:22b9052d864d 497 case TCPSOCKET_READABLE: //Incoming data
va009039 1:22b9052d864d 498 resetTimeout();
va009039 1:22b9052d864d 499 switch(m_state)
va009039 1:22b9052d864d 500 {
va009039 1:22b9052d864d 501 case HTTP_READ_HEADERS:
va009039 1:22b9052d864d 502 if( !readHeaders() )
va009039 1:22b9052d864d 503 {
va009039 1:22b9052d864d 504 return; //Connection has been closed or incomplete data
va009039 1:22b9052d864d 505 }
va009039 1:22b9052d864d 506 if( m_pDataIn )
va009039 1:22b9052d864d 507 {
va009039 1:22b9052d864d 508 //Data chunked?
va009039 1:22b9052d864d 509 if(m_respHeaders["Transfer-Encoding"].find("chunked")!=string::npos)
va009039 1:22b9052d864d 510 {
va009039 1:22b9052d864d 511 m_dataChunked = true;
va009039 1:22b9052d864d 512 m_dataPos = 0;
va009039 1:22b9052d864d 513 m_dataLen = 0;
va009039 1:22b9052d864d 514 DBG("Encoding is chunked, Content-Type is %s\n", m_respHeaders["Content-Type"].c_str() );
va009039 1:22b9052d864d 515 }
va009039 1:22b9052d864d 516 else
va009039 1:22b9052d864d 517 {
va009039 1:22b9052d864d 518 m_dataChunked = false;
va009039 1:22b9052d864d 519 int len = 0;
va009039 1:22b9052d864d 520 //DBG("Preparing read... len = %s\n", m_respHeaders["Content-Length"].c_str());
va009039 1:22b9052d864d 521 sscanf(m_respHeaders["Content-Length"].c_str(), "%d", &len);
va009039 1:22b9052d864d 522 m_pDataIn->setDataLen( len );
va009039 1:22b9052d864d 523 m_dataPos = 0;
va009039 1:22b9052d864d 524 m_dataLen = len;
va009039 1:22b9052d864d 525 DBG("Content-Length is %d, Content-Type is %s\n", len, m_respHeaders["Content-Type"].c_str() );
va009039 1:22b9052d864d 526 }
va009039 1:22b9052d864d 527 m_pDataIn->setDataType( m_respHeaders["Content-Type"] );
va009039 1:22b9052d864d 528 }
va009039 1:22b9052d864d 529 case HTTP_READ_DATA:
va009039 1:22b9052d864d 530 readData();
va009039 1:22b9052d864d 531 break;
va009039 1:22b9052d864d 532 case HTTP_READ_DATA_INCOMPLETE:
va009039 1:22b9052d864d 533 break; //We need to handle previously received data first
va009039 1:22b9052d864d 534 default:
va009039 1:22b9052d864d 535 //Should not receive data now, req is not complete
va009039 1:22b9052d864d 536 onResult(HTTP_PRTCL);
va009039 1:22b9052d864d 537 }
va009039 1:22b9052d864d 538 //All data has been read, close w/ success :)
va009039 1:22b9052d864d 539 if( m_state == HTTP_DONE )
va009039 1:22b9052d864d 540 {
va009039 1:22b9052d864d 541 DBG("Done :)!\n");
va009039 1:22b9052d864d 542 onResult(HTTP_OK);
va009039 1:22b9052d864d 543 }
va009039 1:22b9052d864d 544 break;
va009039 1:22b9052d864d 545 case TCPSOCKET_CONNECTED:
va009039 1:22b9052d864d 546 case TCPSOCKET_WRITEABLE: //We can send data
va009039 1:22b9052d864d 547 resetTimeout();
va009039 1:22b9052d864d 548 switch(m_state)
va009039 1:22b9052d864d 549 {
va009039 1:22b9052d864d 550 case HTTP_WRITE_HEADERS:
va009039 1:22b9052d864d 551 //Update headers fields according to m_pDataOut
va009039 1:22b9052d864d 552 if( m_pDataOut )
va009039 1:22b9052d864d 553 {
va009039 1:22b9052d864d 554 //Data is chunked?
va009039 1:22b9052d864d 555 if(m_pDataOut->getIsChunked())
va009039 1:22b9052d864d 556 {
va009039 1:22b9052d864d 557 m_dataChunked = true;
va009039 1:22b9052d864d 558 m_reqHeaders.erase("Content-Length");
va009039 1:22b9052d864d 559 m_reqHeaders["Transfer-Encoding"] = "chunked";
va009039 1:22b9052d864d 560 }
va009039 1:22b9052d864d 561 else
va009039 1:22b9052d864d 562 {
va009039 1:22b9052d864d 563 m_dataChunked = false;
va009039 1:22b9052d864d 564 char c_len[16] = "0";
va009039 1:22b9052d864d 565 int len = m_pDataOut->getDataLen();
va009039 1:22b9052d864d 566 sprintf(c_len, "%d", len);
va009039 1:22b9052d864d 567 m_dataPos = 0;
va009039 1:22b9052d864d 568 m_dataLen = len;
va009039 1:22b9052d864d 569 m_reqHeaders.erase("Transfer-Encoding");
va009039 1:22b9052d864d 570 m_reqHeaders["Content-Length"] = string(c_len);
va009039 1:22b9052d864d 571 }
va009039 1:22b9052d864d 572 string type = m_pDataOut->getDataType();
va009039 1:22b9052d864d 573 if(!type.empty())
va009039 1:22b9052d864d 574 {
va009039 1:22b9052d864d 575 m_reqHeaders["Content-Type"] = type;
va009039 1:22b9052d864d 576 }
va009039 1:22b9052d864d 577 else
va009039 1:22b9052d864d 578 {
va009039 1:22b9052d864d 579 m_reqHeaders.erase("Content-Type");
va009039 1:22b9052d864d 580 }
va009039 1:22b9052d864d 581 }
va009039 1:22b9052d864d 582 if( !writeHeaders() )
va009039 1:22b9052d864d 583 {
va009039 1:22b9052d864d 584 return; //Connection has been closed
va009039 1:22b9052d864d 585 }
va009039 1:22b9052d864d 586 break; //Wait for writeable event before sending payload
va009039 1:22b9052d864d 587 case HTTP_WRITE_DATA:
va009039 1:22b9052d864d 588 writeData();
va009039 1:22b9052d864d 589 break;
va009039 1:22b9052d864d 590 }
va009039 1:22b9052d864d 591 //Otherwise request has been sent, now wait for resp
va009039 1:22b9052d864d 592 break;
va009039 1:22b9052d864d 593 case TCPSOCKET_CONTIMEOUT:
va009039 1:22b9052d864d 594 case TCPSOCKET_CONRST:
va009039 1:22b9052d864d 595 case TCPSOCKET_CONABRT:
va009039 1:22b9052d864d 596 case TCPSOCKET_ERROR:
va009039 1:22b9052d864d 597 DBG("Connection error.\n");
va009039 1:22b9052d864d 598 onResult(HTTP_CONN);
va009039 1:22b9052d864d 599 case TCPSOCKET_DISCONNECTED:
va009039 1:22b9052d864d 600 //There might still be some data available for reading
va009039 1:22b9052d864d 601 //So if we are in a reading state, do not close the socket yet
va009039 1:22b9052d864d 602 if( (m_state != HTTP_READ_DATA_INCOMPLETE) && (m_state != HTTP_DONE) && (m_state != HTTP_CLOSED) )
va009039 1:22b9052d864d 603 {
va009039 1:22b9052d864d 604 onResult(HTTP_CONN);
va009039 1:22b9052d864d 605 }
va009039 1:22b9052d864d 606 DBG("Connection closed by remote host.\n");
va009039 1:22b9052d864d 607 break;
va009039 1:22b9052d864d 608 }
va009039 1:22b9052d864d 609 }
va009039 1:22b9052d864d 610
va009039 1:22b9052d864d 611 void HTTPClient::onDNSReply(DNSReply r)
va009039 1:22b9052d864d 612 {
va009039 1:22b9052d864d 613 if(m_closed)
va009039 1:22b9052d864d 614 {
va009039 1:22b9052d864d 615 DBG("WARN: Discarded\n");
va009039 1:22b9052d864d 616 return;
va009039 1:22b9052d864d 617 }
va009039 1:22b9052d864d 618
va009039 1:22b9052d864d 619 if( r != DNS_FOUND )
va009039 1:22b9052d864d 620 {
va009039 1:22b9052d864d 621 DBG("Could not resolve hostname.\n");
va009039 1:22b9052d864d 622 onResult(HTTP_DNS);
va009039 1:22b9052d864d 623 return;
va009039 1:22b9052d864d 624 }
va009039 1:22b9052d864d 625
va009039 1:22b9052d864d 626 DBG("DNS Resolved to %d.%d.%d.%d.\n",m_server.getIp()[0],m_server.getIp()[1],m_server.getIp()[2],m_server.getIp()[3]);
va009039 1:22b9052d864d 627 //If no error, m_server has been updated by m_pDnsReq so we're set to go !
va009039 1:22b9052d864d 628 m_pDnsReq->close();
va009039 1:22b9052d864d 629 delete m_pDnsReq;
va009039 1:22b9052d864d 630 m_pDnsReq = NULL;
va009039 1:22b9052d864d 631 connect();
va009039 1:22b9052d864d 632 }
va009039 1:22b9052d864d 633
va009039 1:22b9052d864d 634 void HTTPClient::onResult(HTTPResult r) //Called when exchange completed or on failure
va009039 1:22b9052d864d 635 {
va009039 1:22b9052d864d 636 if(m_pCbItem && m_pCbMeth)
va009039 1:22b9052d864d 637 (m_pCbItem->*m_pCbMeth)(r);
va009039 1:22b9052d864d 638 else if(m_pCb)
va009039 1:22b9052d864d 639 m_pCb(r);
va009039 1:22b9052d864d 640 m_blockingResult = r; //Blocking mode
va009039 1:22b9052d864d 641 close(); //FIXME:Remove suppl. close() calls
va009039 1:22b9052d864d 642 }
va009039 1:22b9052d864d 643
va009039 1:22b9052d864d 644 void HTTPClient::onTimeout() //Connection has timed out
va009039 1:22b9052d864d 645 {
va009039 1:22b9052d864d 646 DBG("Timed out.\n");
va009039 1:22b9052d864d 647 onResult(HTTP_TIMEOUT);
va009039 1:22b9052d864d 648 close();
va009039 1:22b9052d864d 649 }
va009039 1:22b9052d864d 650
va009039 1:22b9052d864d 651 //Headers
va009039 1:22b9052d864d 652
va009039 1:22b9052d864d 653 //TODO: Factorize w/ HTTPRequestHandler in a single HTTPHeader class
va009039 1:22b9052d864d 654
va009039 1:22b9052d864d 655 HTTPResult HTTPClient::blockingProcess() //Called in blocking mode, calls Net::poll() until return code is available
va009039 1:22b9052d864d 656 {
va009039 1:22b9052d864d 657 //Disable callbacks
va009039 1:22b9052d864d 658 m_pCb = NULL;
va009039 1:22b9052d864d 659 m_pCbItem = NULL;
va009039 1:22b9052d864d 660 m_pCbMeth = NULL;
va009039 1:22b9052d864d 661 m_blockingResult = HTTP_PROCESSING;
va009039 1:22b9052d864d 662 do
va009039 1:22b9052d864d 663 {
va009039 1:22b9052d864d 664 Net::poll();
va009039 1:22b9052d864d 665 } while(m_blockingResult == HTTP_PROCESSING);
va009039 1:22b9052d864d 666 Net::poll(); //Necessary for cleanup
va009039 1:22b9052d864d 667 return m_blockingResult;
va009039 1:22b9052d864d 668 }
va009039 1:22b9052d864d 669
va009039 1:22b9052d864d 670 bool HTTPClient::readHeaders()
va009039 1:22b9052d864d 671 {
va009039 1:22b9052d864d 672 static char* line = m_buf;
va009039 1:22b9052d864d 673 static char key[128];
va009039 1:22b9052d864d 674 static char value[128];
va009039 1:22b9052d864d 675 if(!m_dataLen) //No incomplete header in buffer, this is the first time we read data
va009039 1:22b9052d864d 676 {
va009039 1:22b9052d864d 677 if( readLine(line, 128) > 0 )
va009039 1:22b9052d864d 678 {
va009039 1:22b9052d864d 679 //Check RC
va009039 1:22b9052d864d 680 m_httpResponseCode = 0;
va009039 1:22b9052d864d 681 if( sscanf(line, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 )
va009039 1:22b9052d864d 682 {
va009039 1:22b9052d864d 683 //Cannot match string, error
va009039 1:22b9052d864d 684 DBG("Not a correct HTTP answer : %s\n", line);
va009039 1:22b9052d864d 685 onResult(HTTP_PRTCL);
va009039 1:22b9052d864d 686 close();
va009039 1:22b9052d864d 687 return false;
va009039 1:22b9052d864d 688 }
va009039 1:22b9052d864d 689
va009039 1:22b9052d864d 690 if(m_httpResponseCode != 200)
va009039 1:22b9052d864d 691 {
va009039 1:22b9052d864d 692 DBG("Response: error code %d\n", m_httpResponseCode);
va009039 1:22b9052d864d 693 HTTPResult res = HTTP_ERROR;
va009039 1:22b9052d864d 694 switch(m_httpResponseCode)
va009039 1:22b9052d864d 695 {
va009039 1:22b9052d864d 696 case 404:
va009039 1:22b9052d864d 697 res = HTTP_NOTFOUND;
va009039 1:22b9052d864d 698 break;
va009039 1:22b9052d864d 699 case 403:
va009039 1:22b9052d864d 700 res = HTTP_REFUSED;
va009039 1:22b9052d864d 701 break;
va009039 1:22b9052d864d 702 default:
va009039 1:22b9052d864d 703 res = HTTP_ERROR;
va009039 1:22b9052d864d 704 }
va009039 1:22b9052d864d 705 onResult(res);
va009039 1:22b9052d864d 706 close();
va009039 1:22b9052d864d 707 return false;
va009039 1:22b9052d864d 708 }
va009039 1:22b9052d864d 709 DBG("Response OK\n");
va009039 1:22b9052d864d 710 }
va009039 1:22b9052d864d 711 else
va009039 1:22b9052d864d 712 {
va009039 1:22b9052d864d 713 //Empty packet, weird!
va009039 1:22b9052d864d 714 DBG("Empty packet!\n");
va009039 1:22b9052d864d 715 onResult(HTTP_PRTCL);
va009039 1:22b9052d864d 716 close();
va009039 1:22b9052d864d 717 return false;
va009039 1:22b9052d864d 718 }
va009039 1:22b9052d864d 719 }
va009039 1:22b9052d864d 720 bool incomplete = false;
va009039 1:22b9052d864d 721 while( true )
va009039 1:22b9052d864d 722 {
va009039 1:22b9052d864d 723 int readLen = readLine(line + m_dataLen, 128 - m_dataLen, &incomplete);
va009039 1:22b9052d864d 724 m_dataLen = 0;
va009039 1:22b9052d864d 725 if( readLen <= 2 ) //if == 1 or 2, it is an empty line = end of headers
va009039 1:22b9052d864d 726 {
va009039 1:22b9052d864d 727 DBG("All headers read.\n");
va009039 1:22b9052d864d 728 m_state = HTTP_READ_DATA;
va009039 1:22b9052d864d 729 break;
va009039 1:22b9052d864d 730 }
va009039 1:22b9052d864d 731 else if( incomplete == true )
va009039 1:22b9052d864d 732 {
va009039 1:22b9052d864d 733 m_dataLen = readLen;//Sets data length available in buffer
va009039 1:22b9052d864d 734 return false;
va009039 1:22b9052d864d 735 }
va009039 1:22b9052d864d 736 //DBG("Header : %s\n", line);
va009039 1:22b9052d864d 737 int n = sscanf(line, "%[^:] : %[^\r\n]", key, value);
va009039 1:22b9052d864d 738 if ( n == 2 )
va009039 1:22b9052d864d 739 {
va009039 1:22b9052d864d 740 DBG("Read header : %s: %s\n", key, value);
va009039 1:22b9052d864d 741 m_respHeaders[key] = value;
va009039 1:22b9052d864d 742 }
va009039 1:22b9052d864d 743 //TODO: Impl n==1 case (part 2 of previous header)
va009039 1:22b9052d864d 744 }
va009039 1:22b9052d864d 745
va009039 1:22b9052d864d 746 return true;
va009039 1:22b9052d864d 747 }
va009039 1:22b9052d864d 748
va009039 1:22b9052d864d 749 bool HTTPClient::writeHeaders() //Called at the first writeData call
va009039 1:22b9052d864d 750 {
va009039 1:22b9052d864d 751 static char* line = m_buf;
va009039 1:22b9052d864d 752 const char* HTTP_METH_STR[] = {"GET", "POST", "HEAD"};
va009039 1:22b9052d864d 753
va009039 1:22b9052d864d 754 //Req
va009039 1:22b9052d864d 755 sprintf(line, "%s %s HTTP/1.1\r\nHost: %s\r\n", HTTP_METH_STR[m_meth], m_path.c_str(), m_server.getName()); //Write request
va009039 1:22b9052d864d 756 m_pTCPSocket->send(line, strlen(line));
va009039 1:22b9052d864d 757 DBG("Request: %s\n", line);
va009039 1:22b9052d864d 758
va009039 1:22b9052d864d 759 DBG("Writing headers:\n");
va009039 1:22b9052d864d 760 map<string,string>::iterator it;
va009039 1:22b9052d864d 761 for( it = m_reqHeaders.begin(); it != m_reqHeaders.end(); it++ )
va009039 1:22b9052d864d 762 {
va009039 1:22b9052d864d 763 sprintf(line, "%s: %s\r\n", (*it).first.c_str(), (*it).second.c_str() );
va009039 1:22b9052d864d 764 DBG("\r\n%s", line);
va009039 1:22b9052d864d 765 m_pTCPSocket->send(line, strlen(line));
va009039 1:22b9052d864d 766 }
va009039 1:22b9052d864d 767 m_pTCPSocket->send("\r\n",2); //End of head
va009039 1:22b9052d864d 768 m_state = HTTP_WRITE_DATA;
va009039 1:22b9052d864d 769 return true;
va009039 1:22b9052d864d 770 }
va009039 1:22b9052d864d 771
va009039 1:22b9052d864d 772 int HTTPClient::readLine(char* str, int maxLen, bool* pIncomplete /* = NULL*/)
va009039 1:22b9052d864d 773 {
va009039 1:22b9052d864d 774 int ret;
va009039 1:22b9052d864d 775 int len = 0;
va009039 1:22b9052d864d 776 if(pIncomplete)
va009039 1:22b9052d864d 777 *pIncomplete = false;
va009039 1:22b9052d864d 778 for(int i = 0; i < maxLen - 1; i++)
va009039 1:22b9052d864d 779 {
va009039 1:22b9052d864d 780 ret = m_pTCPSocket->recv(str, 1);
va009039 1:22b9052d864d 781 if(ret != 1)
va009039 1:22b9052d864d 782 {
va009039 1:22b9052d864d 783 if(pIncomplete)
va009039 1:22b9052d864d 784 *pIncomplete = true;
va009039 1:22b9052d864d 785 break;
va009039 1:22b9052d864d 786 }
va009039 1:22b9052d864d 787 if( (len > 1) && *(str-1)=='\r' && *str=='\n' )
va009039 1:22b9052d864d 788 {
va009039 1:22b9052d864d 789 break;
va009039 1:22b9052d864d 790 }
va009039 1:22b9052d864d 791 else if( *str=='\n' )
va009039 1:22b9052d864d 792 {
va009039 1:22b9052d864d 793 break;
va009039 1:22b9052d864d 794 }
va009039 1:22b9052d864d 795 str++;
va009039 1:22b9052d864d 796 len++;
va009039 1:22b9052d864d 797 }
va009039 1:22b9052d864d 798 *str = 0;
va009039 1:22b9052d864d 799 return len;
va009039 1:22b9052d864d 800 }
va009039 1:22b9052d864d 801
va009039 1:22b9052d864d 802 #define CR(R) case R: return #R
va009039 1:22b9052d864d 803 char* HTTPClient::ResultStr(HTTPResult r)
va009039 1:22b9052d864d 804 {
va009039 1:22b9052d864d 805 switch(r) {
va009039 1:22b9052d864d 806 CR(HTTP_OK); ///<Success
va009039 1:22b9052d864d 807 CR(HTTP_PROCESSING); ///<Processing
va009039 1:22b9052d864d 808 CR(HTTP_PARSE); ///<URI Parse error
va009039 1:22b9052d864d 809 CR(HTTP_DNS); ///<Could not resolve name
va009039 1:22b9052d864d 810 CR(HTTP_PRTCL); ///<Protocol error
va009039 1:22b9052d864d 811 CR(HTTP_NOTFOUND); ///<HTTP 404 Error
va009039 1:22b9052d864d 812 CR(HTTP_REFUSED); ///<HTTP 403 Error
va009039 1:22b9052d864d 813 CR(HTTP_ERROR); ///<HTTP xxx error
va009039 1:22b9052d864d 814 CR(HTTP_TIMEOUT); ///<Connection timeout
va009039 1:22b9052d864d 815 CR(HTTP_CONN); ///<Connection error
va009039 1:22b9052d864d 816 }
va009039 1:22b9052d864d 817 return "Unknown HTTPResult";
va009039 1:22b9052d864d 818 }