http

Dependents:   finalV1 finalV1 finalv2 finalv3

Committer:
yihui
Date:
Fri Mar 06 09:22:06 2015 +0000
Revision:
18:aaab2081c1c0
Parent:
17:f22357c94c81
update url - mbed.org/* to developer.mbed.org and increase buffer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donatien 0:2ccb9960a044 1 /* HTTPClient.cpp */
donatien 10:e1351de84c16 2 /* Copyright (C) 2012 mbed.org, MIT License
donatien 10:e1351de84c16 3 *
donatien 10:e1351de84c16 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
donatien 10:e1351de84c16 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
donatien 10:e1351de84c16 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
donatien 10:e1351de84c16 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
donatien 10:e1351de84c16 8 * furnished to do so, subject to the following conditions:
donatien 10:e1351de84c16 9 *
donatien 10:e1351de84c16 10 * The above copyright notice and this permission notice shall be included in all copies or
donatien 10:e1351de84c16 11 * substantial portions of the Software.
donatien 10:e1351de84c16 12 *
donatien 10:e1351de84c16 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
donatien 10:e1351de84c16 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
donatien 10:e1351de84c16 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
donatien 10:e1351de84c16 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
donatien 10:e1351de84c16 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
donatien 10:e1351de84c16 18 */
donatien 0:2ccb9960a044 19
donatien 7:4e39864f7b15 20 //Debug is disabled by default
donatien 16:1f743885e7de 21 #if 0
donatien 12:89d09a6db00a 22 //Enable debug
donatien 11:390362de8c3f 23 #include <cstdio>
lawliet 17:f22357c94c81 24 #define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__);
lawliet 17:f22357c94c81 25 #define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__);
lawliet 17:f22357c94c81 26 #define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__);
donatien 12:89d09a6db00a 27
donatien 12:89d09a6db00a 28 #else
donatien 12:89d09a6db00a 29 //Disable debug
lawliet 17:f22357c94c81 30 #define DBG(x, ...)
donatien 12:89d09a6db00a 31 #define WARN(x, ...)
lawliet 17:f22357c94c81 32 #define ERR(x, ...)
donatien 12:89d09a6db00a 33
donatien 7:4e39864f7b15 34 #endif
donatien 0:2ccb9960a044 35
donatien 0:2ccb9960a044 36 #define HTTP_PORT 80
donatien 0:2ccb9960a044 37
donatien 11:390362de8c3f 38 #define OK 0
donatien 11:390362de8c3f 39
donatien 11:390362de8c3f 40 #define MIN(x,y) (((x)<(y))?(x):(y))
donatien 11:390362de8c3f 41 #define MAX(x,y) (((x)>(y))?(x):(y))
donatien 11:390362de8c3f 42
yihui 18:aaab2081c1c0 43 #define CHUNK_SIZE 1024
donatien 0:2ccb9960a044 44
donatien 0:2ccb9960a044 45 #include <cstring>
donatien 0:2ccb9960a044 46
donatien 11:390362de8c3f 47 #include "HTTPClient.h"
donatien 11:390362de8c3f 48
donatien 0:2ccb9960a044 49 HTTPClient::HTTPClient() :
lawliet 17:f22357c94c81 50 m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
donatien 0:2ccb9960a044 51 {
donatien 0:2ccb9960a044 52
donatien 0:2ccb9960a044 53 }
donatien 0:2ccb9960a044 54
donatien 0:2ccb9960a044 55 HTTPClient::~HTTPClient()
donatien 0:2ccb9960a044 56 {
donatien 0:2ccb9960a044 57
donatien 0:2ccb9960a044 58 }
donatien 0:2ccb9960a044 59
donatien 0:2ccb9960a044 60 #if 0
donatien 0:2ccb9960a044 61 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
donatien 0:2ccb9960a044 62 {
lawliet 17:f22357c94c81 63 m_basicAuthUser = user;
lawliet 17:f22357c94c81 64 m_basicAuthPassword = password;
donatien 0:2ccb9960a044 65 }
donatien 0:2ccb9960a044 66 #endif
donatien 0:2ccb9960a044 67
donatien 12:89d09a6db00a 68 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 0:2ccb9960a044 69 {
lawliet 17:f22357c94c81 70 return connect(url, HTTP_GET, NULL, pDataIn, timeout);
donatien 0:2ccb9960a044 71 }
donatien 0:2ccb9960a044 72
donatien 12:89d09a6db00a 73 HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 0:2ccb9960a044 74 {
lawliet 17:f22357c94c81 75 HTTPText str(result, maxResultLen);
lawliet 17:f22357c94c81 76 return get(url, &str, timeout);
donatien 0:2ccb9960a044 77 }
donatien 0:2ccb9960a044 78
donatien 12:89d09a6db00a 79 HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 0:2ccb9960a044 80 {
lawliet 17:f22357c94c81 81 return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
donatien 0:2ccb9960a044 82 }
donatien 0:2ccb9960a044 83
donatien 16:1f743885e7de 84 HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 16:1f743885e7de 85 {
lawliet 17:f22357c94c81 86 return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
donatien 16:1f743885e7de 87 }
donatien 16:1f743885e7de 88
donatien 16:1f743885e7de 89 HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 16:1f743885e7de 90 {
lawliet 17:f22357c94c81 91 return connect(url, HTTP_DELETE, NULL, pDataIn, timeout);
donatien 16:1f743885e7de 92 }
donatien 16:1f743885e7de 93
donatien 16:1f743885e7de 94
donatien 0:2ccb9960a044 95 int HTTPClient::getHTTPResponseCode()
donatien 0:2ccb9960a044 96 {
lawliet 17:f22357c94c81 97 return m_httpResponseCode;
donatien 0:2ccb9960a044 98 }
donatien 0:2ccb9960a044 99
donatien 5:791fc3dcb6c4 100 #define CHECK_CONN_ERR(ret) \
donatien 5:791fc3dcb6c4 101 do{ \
donatien 7:4e39864f7b15 102 if(ret) { \
donatien 7:4e39864f7b15 103 m_sock.close(); \
donatien 5:791fc3dcb6c4 104 ERR("Connection error (%d)", ret); \
donatien 11:390362de8c3f 105 return HTTP_CONN; \
donatien 5:791fc3dcb6c4 106 } \
donatien 5:791fc3dcb6c4 107 } while(0)
donatien 5:791fc3dcb6c4 108
donatien 5:791fc3dcb6c4 109 #define PRTCL_ERR() \
donatien 5:791fc3dcb6c4 110 do{ \
donatien 7:4e39864f7b15 111 m_sock.close(); \
donatien 5:791fc3dcb6c4 112 ERR("Protocol error"); \
donatien 11:390362de8c3f 113 return HTTP_PRTCL; \
donatien 5:791fc3dcb6c4 114 } while(0)
donatien 0:2ccb9960a044 115
donatien 12:89d09a6db00a 116 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request
lawliet 17:f22357c94c81 117 {
lawliet 17:f22357c94c81 118 m_httpResponseCode = 0; //Invalidate code
lawliet 17:f22357c94c81 119 m_timeout = timeout;
lawliet 17:f22357c94c81 120
lawliet 17:f22357c94c81 121 pDataIn->writeReset();
lawliet 17:f22357c94c81 122 if( pDataOut ) {
lawliet 17:f22357c94c81 123 pDataOut->readReset();
lawliet 17:f22357c94c81 124 }
donatien 0:2ccb9960a044 125
lawliet 17:f22357c94c81 126 char scheme[8];
lawliet 17:f22357c94c81 127 uint16_t port;
lawliet 17:f22357c94c81 128 char host[32];
lawliet 17:f22357c94c81 129 char path[64];
lawliet 17:f22357c94c81 130 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?)
lawliet 17:f22357c94c81 131 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
lawliet 17:f22357c94c81 132 if(res != HTTP_OK) {
lawliet 17:f22357c94c81 133 ERR("parseURL returned %d", res);
lawliet 17:f22357c94c81 134 return res;
lawliet 17:f22357c94c81 135 }
donatien 0:2ccb9960a044 136
lawliet 17:f22357c94c81 137 if(port == 0) { //TODO do handle HTTPS->443
lawliet 17:f22357c94c81 138 port = 80;
lawliet 17:f22357c94c81 139 }
donatien 0:2ccb9960a044 140
lawliet 17:f22357c94c81 141 DBG("Scheme: %s", scheme);
lawliet 17:f22357c94c81 142 DBG("Host: %s", host);
lawliet 17:f22357c94c81 143 DBG("Port: %d", port);
lawliet 17:f22357c94c81 144 DBG("Path: %s", path);
donatien 0:2ccb9960a044 145
lawliet 17:f22357c94c81 146 //Connect
lawliet 17:f22357c94c81 147 DBG("Connecting socket to server");
lawliet 17:f22357c94c81 148 int ret = m_sock.connect(host, port);
lawliet 17:f22357c94c81 149 if (ret < 1) {
lawliet 17:f22357c94c81 150 m_sock.close();
lawliet 17:f22357c94c81 151 ERR("Could not connect");
lawliet 17:f22357c94c81 152 return HTTP_CONN;
lawliet 17:f22357c94c81 153 }
donatien 0:2ccb9960a044 154
lawliet 17:f22357c94c81 155 //Send request
lawliet 17:f22357c94c81 156 DBG("Sending request");
lawliet 17:f22357c94c81 157 char buf[CHUNK_SIZE];
lawliet 17:f22357c94c81 158 memset(buf,'\0',sizeof(buf));
lawliet 17:f22357c94c81 159 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":"";
lawliet 17:f22357c94c81 160 snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request
donatien 0:2ccb9960a044 161
lawliet 17:f22357c94c81 162 DBG("Sending headers");
lawliet 17:f22357c94c81 163 if( pDataOut != NULL ) {
lawliet 17:f22357c94c81 164 if( pDataOut->getIsChunked() ) {
lawliet 17:f22357c94c81 165 ret = send("Transfer-Encoding: chunked\r\n");
lawliet 17:f22357c94c81 166 CHECK_CONN_ERR(ret);
lawliet 17:f22357c94c81 167 } else {
lawliet 17:f22357c94c81 168 snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),"Content-Length: %d\r\n", pDataOut->getDataLen());
lawliet 17:f22357c94c81 169 }
lawliet 17:f22357c94c81 170 char type[48];
lawliet 17:f22357c94c81 171 if( pDataOut->getDataType(type, 48) == HTTP_OK ) {
lawliet 17:f22357c94c81 172 snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),"Content-Type: %s\r\n", type);
lawliet 17:f22357c94c81 173 }
donatien 0:2ccb9960a044 174 }
lawliet 17:f22357c94c81 175
lawliet 17:f22357c94c81 176 strcpy(buf+strlen(buf),"\r\n");
lawliet 17:f22357c94c81 177
lawliet 17:f22357c94c81 178 size_t trfLen;
lawliet 17:f22357c94c81 179
lawliet 17:f22357c94c81 180 //Send data (if available)
lawliet 17:f22357c94c81 181 if( pDataOut != NULL ) {
lawliet 17:f22357c94c81 182 DBG("Sending data");
lawliet 17:f22357c94c81 183 while(true) {
lawliet 17:f22357c94c81 184 size_t writtenLen = 0;
lawliet 17:f22357c94c81 185 pDataOut->read(buf+strlen(buf), CHUNK_SIZE, &trfLen);
lawliet 17:f22357c94c81 186 if(pDataOut->getIsChunked()) {
lawliet 17:f22357c94c81 187 //Write chunk header
lawliet 17:f22357c94c81 188 char chunkHeader[16];
lawliet 17:f22357c94c81 189 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
lawliet 17:f22357c94c81 190 ret = send(chunkHeader);
lawliet 17:f22357c94c81 191 CHECK_CONN_ERR(ret);
lawliet 17:f22357c94c81 192 } else if( trfLen == 0 ) {
lawliet 17:f22357c94c81 193 break;
lawliet 17:f22357c94c81 194 }
lawliet 17:f22357c94c81 195
lawliet 17:f22357c94c81 196 if( pDataOut->getIsChunked()) {
lawliet 17:f22357c94c81 197 ret = send("\r\n"); //Chunk-terminating CRLF
lawliet 17:f22357c94c81 198 CHECK_CONN_ERR(ret);
lawliet 17:f22357c94c81 199 } else {
lawliet 17:f22357c94c81 200 writtenLen += trfLen;
lawliet 17:f22357c94c81 201 if( writtenLen >= pDataOut->getDataLen()) {
lawliet 17:f22357c94c81 202 break;
lawliet 17:f22357c94c81 203 }
lawliet 17:f22357c94c81 204 }
donatien 0:2ccb9960a044 205
lawliet 17:f22357c94c81 206 if( trfLen == 0 ) {
lawliet 17:f22357c94c81 207 break;
lawliet 17:f22357c94c81 208 }
lawliet 17:f22357c94c81 209 }
lawliet 17:f22357c94c81 210 }
lawliet 17:f22357c94c81 211 m_sock.send_all(buf,strlen(buf));
lawliet 17:f22357c94c81 212 memset(buf,'\0',sizeof(buf));
lawliet 17:f22357c94c81 213 trfLen = m_sock.receive(buf, sizeof(buf)-1);
lawliet 17:f22357c94c81 214 buf[trfLen] = '\0';
lawliet 17:f22357c94c81 215 char* crlfPtr = strstr(buf, "\r\n");
lawliet 17:f22357c94c81 216 if(crlfPtr == NULL) {
lawliet 17:f22357c94c81 217 PRTCL_ERR();
lawliet 17:f22357c94c81 218 }
lawliet 17:f22357c94c81 219
lawliet 17:f22357c94c81 220 int crlfPos = crlfPtr - buf;
lawliet 17:f22357c94c81 221 buf[crlfPos] = '\0';
donatien 0:2ccb9960a044 222
lawliet 17:f22357c94c81 223 //Parse HTTP response
lawliet 17:f22357c94c81 224 if(1 != sscanf(buf, "\nHTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode)) {
lawliet 17:f22357c94c81 225 //Cannot match string, error
lawliet 17:f22357c94c81 226 ERR("Not a correct HTTP answer : %s\n", buf);
lawliet 17:f22357c94c81 227 PRTCL_ERR();
lawliet 17:f22357c94c81 228 }
lawliet 17:f22357c94c81 229
lawliet 17:f22357c94c81 230 DBG("m_httpResponseCode = %d\n",m_httpResponseCode);
lawliet 17:f22357c94c81 231
lawliet 17:f22357c94c81 232 if((method == HTTP_PUT) || (method == HTTP_POST) || (method == HTTP_DELETE)) {
lawliet 17:f22357c94c81 233 m_sock.close();
lawliet 17:f22357c94c81 234 if((m_httpResponseCode >= 200) && (m_httpResponseCode < 300)) {
lawliet 17:f22357c94c81 235 return HTTP_OK;
lawliet 17:f22357c94c81 236 } else {
lawliet 17:f22357c94c81 237 return HTTP_ERROR;
donatien 0:2ccb9960a044 238 }
lawliet 17:f22357c94c81 239 }
donatien 0:2ccb9960a044 240
lawliet 17:f22357c94c81 241 if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) ) {
lawliet 17:f22357c94c81 242 //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers
lawliet 17:f22357c94c81 243 WARN("Response code %d", m_httpResponseCode);
lawliet 17:f22357c94c81 244 PRTCL_ERR();
donatien 0:2ccb9960a044 245 }
donatien 0:2ccb9960a044 246
lawliet 17:f22357c94c81 247 DBG("Reading headers");
lawliet 17:f22357c94c81 248 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
lawliet 17:f22357c94c81 249 trfLen -= (crlfPos + 2);
donatien 0:2ccb9960a044 250
lawliet 17:f22357c94c81 251 size_t recvContentLength = 0;
lawliet 17:f22357c94c81 252 bool recvChunked = false;
lawliet 17:f22357c94c81 253 //Now get headers
lawliet 17:f22357c94c81 254 while( true ) {
lawliet 17:f22357c94c81 255 crlfPtr = strstr(buf, "\r\n");
lawliet 17:f22357c94c81 256 if(crlfPtr == NULL) {
lawliet 17:f22357c94c81 257 if( trfLen < CHUNK_SIZE - 1 ) {
lawliet 17:f22357c94c81 258 size_t newTrfLen = 0;
lawliet 17:f22357c94c81 259 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
lawliet 17:f22357c94c81 260 trfLen += newTrfLen;
lawliet 17:f22357c94c81 261 buf[trfLen] = '\0';
lawliet 17:f22357c94c81 262 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
lawliet 17:f22357c94c81 263 CHECK_CONN_ERR(ret);
lawliet 17:f22357c94c81 264 continue;
lawliet 17:f22357c94c81 265 } else {
lawliet 17:f22357c94c81 266 PRTCL_ERR();
lawliet 17:f22357c94c81 267 }
lawliet 17:f22357c94c81 268 }
donatien 0:2ccb9960a044 269
lawliet 17:f22357c94c81 270 crlfPos = crlfPtr - buf;
donatien 0:2ccb9960a044 271
lawliet 17:f22357c94c81 272 if(crlfPos == 0) { //End of headers
lawliet 17:f22357c94c81 273 DBG("Headers read");
lawliet 17:f22357c94c81 274 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
lawliet 17:f22357c94c81 275 trfLen -= 2;
lawliet 17:f22357c94c81 276 break;
lawliet 17:f22357c94c81 277 }
lawliet 17:f22357c94c81 278 buf[crlfPos] = '\0';
lawliet 17:f22357c94c81 279 char key[32];
lawliet 17:f22357c94c81 280 char value[32];
donatien 0:2ccb9960a044 281
lawliet 17:f22357c94c81 282 key[31] = '\0';
lawliet 17:f22357c94c81 283 value[31] = '\0';
donatien 0:2ccb9960a044 284
lawliet 17:f22357c94c81 285 int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
lawliet 17:f22357c94c81 286 if ( n == 2 ) {
lawliet 17:f22357c94c81 287 DBG("Read header : %s: %s\n", key, value);
lawliet 17:f22357c94c81 288 if( !strcmp(key, "Content-Length") ) {
lawliet 17:f22357c94c81 289 sscanf(value, "%d", &recvContentLength);
lawliet 17:f22357c94c81 290 pDataIn->setDataLen(recvContentLength);
lawliet 17:f22357c94c81 291 } else if( !strcmp(key, "Transfer-Encoding") ) {
lawliet 17:f22357c94c81 292 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) {
lawliet 17:f22357c94c81 293 recvChunked = true;
lawliet 17:f22357c94c81 294 pDataIn->setIsChunked(true);
lawliet 17:f22357c94c81 295 }
lawliet 17:f22357c94c81 296 } else if( !strcmp(key, "Content-Type") ) {
lawliet 17:f22357c94c81 297 pDataIn->setDataType(value);
lawliet 17:f22357c94c81 298 }
donatien 4:c071b05ac026 299
lawliet 17:f22357c94c81 300 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
lawliet 17:f22357c94c81 301 trfLen -= (crlfPos + 2);
lawliet 17:f22357c94c81 302 } else {
lawliet 17:f22357c94c81 303 ERR("Could not parse header");
lawliet 17:f22357c94c81 304 PRTCL_ERR();
donatien 0:2ccb9960a044 305 }
donatien 0:2ccb9960a044 306 }
donatien 0:2ccb9960a044 307
lawliet 17:f22357c94c81 308 //Receive data
lawliet 17:f22357c94c81 309 DBG("Receiving data");
lawliet 17:f22357c94c81 310 while(true) {
lawliet 17:f22357c94c81 311 size_t readLen = 0;
lawliet 17:f22357c94c81 312 if( recvChunked ) {
lawliet 17:f22357c94c81 313 //Read chunk header
lawliet 17:f22357c94c81 314 bool foundCrlf;
lawliet 17:f22357c94c81 315 do {
lawliet 17:f22357c94c81 316 foundCrlf = false;
lawliet 17:f22357c94c81 317 crlfPos=0;
lawliet 17:f22357c94c81 318 buf[trfLen]=0;
lawliet 17:f22357c94c81 319 if(trfLen >= 2) {
lawliet 17:f22357c94c81 320 for(; crlfPos < trfLen - 2; crlfPos++) {
lawliet 17:f22357c94c81 321 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) {
lawliet 17:f22357c94c81 322 foundCrlf = true;
lawliet 17:f22357c94c81 323 break;
lawliet 17:f22357c94c81 324 }
lawliet 17:f22357c94c81 325 }
lawliet 17:f22357c94c81 326 }
lawliet 17:f22357c94c81 327 if(!foundCrlf) { //Try to read more
lawliet 17:f22357c94c81 328 if( trfLen < CHUNK_SIZE ) {
lawliet 17:f22357c94c81 329 size_t newTrfLen = 0;
lawliet 17:f22357c94c81 330 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
lawliet 17:f22357c94c81 331 trfLen += newTrfLen;
lawliet 17:f22357c94c81 332 CHECK_CONN_ERR(ret);
lawliet 17:f22357c94c81 333 continue;
lawliet 17:f22357c94c81 334 } else {
lawliet 17:f22357c94c81 335 PRTCL_ERR();
lawliet 17:f22357c94c81 336 }
lawliet 17:f22357c94c81 337 }
lawliet 17:f22357c94c81 338 } while(!foundCrlf);
lawliet 17:f22357c94c81 339 buf[crlfPos] = '\0';
lawliet 17:f22357c94c81 340 int n = sscanf(buf, "%x", &readLen);
lawliet 17:f22357c94c81 341 if(n!=1) {
lawliet 17:f22357c94c81 342 ERR("Could not read chunk length");
lawliet 17:f22357c94c81 343 PRTCL_ERR();
lawliet 17:f22357c94c81 344 }
donatien 0:2ccb9960a044 345
lawliet 17:f22357c94c81 346 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
lawliet 17:f22357c94c81 347 trfLen -= (crlfPos + 2);
lawliet 17:f22357c94c81 348
lawliet 17:f22357c94c81 349 if( readLen == 0 ) {
lawliet 17:f22357c94c81 350 //Last chunk
lawliet 17:f22357c94c81 351 break;
donatien 14:2744e0c0e527 352 }
lawliet 17:f22357c94c81 353 } else {
lawliet 17:f22357c94c81 354 if(recvContentLength != 0)
lawliet 17:f22357c94c81 355 readLen = recvContentLength;
lawliet 17:f22357c94c81 356 else
lawliet 17:f22357c94c81 357 readLen = strlen(buf);
lawliet 17:f22357c94c81 358 printf("data len = %d",readLen);
donatien 0:2ccb9960a044 359 }
lawliet 17:f22357c94c81 360
lawliet 17:f22357c94c81 361 DBG("Retrieving %d bytes", readLen);
lawliet 17:f22357c94c81 362
lawliet 17:f22357c94c81 363 do {
lawliet 17:f22357c94c81 364 pDataIn->write(buf, MIN(trfLen, readLen));
lawliet 17:f22357c94c81 365 if( trfLen > readLen ) {
lawliet 17:f22357c94c81 366 memmove(buf, &buf[readLen], trfLen - readLen);
lawliet 17:f22357c94c81 367 trfLen -= readLen;
lawliet 17:f22357c94c81 368 readLen = 0;
lawliet 17:f22357c94c81 369 } else {
lawliet 17:f22357c94c81 370 readLen -= trfLen;
lawliet 17:f22357c94c81 371 }
lawliet 17:f22357c94c81 372
lawliet 17:f22357c94c81 373 if(readLen) {
lawliet 17:f22357c94c81 374 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
lawliet 17:f22357c94c81 375 CHECK_CONN_ERR(ret);
lawliet 17:f22357c94c81 376 }
lawliet 17:f22357c94c81 377 } while(readLen);
lawliet 17:f22357c94c81 378 if( recvChunked ) {
lawliet 17:f22357c94c81 379 if(trfLen < 2) {
lawliet 17:f22357c94c81 380 size_t newTrfLen = 0;
lawliet 17:f22357c94c81 381 //Read missing chars to find end of chunk
lawliet 17:f22357c94c81 382 ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen);
lawliet 17:f22357c94c81 383 CHECK_CONN_ERR(ret);
lawliet 17:f22357c94c81 384 trfLen += newTrfLen;
lawliet 17:f22357c94c81 385 }
lawliet 17:f22357c94c81 386 if( (buf[0] != '\r') || (buf[1] != '\n') ) {
lawliet 17:f22357c94c81 387 ERR("Format error");
lawliet 17:f22357c94c81 388 PRTCL_ERR();
lawliet 17:f22357c94c81 389 }
lawliet 17:f22357c94c81 390 memmove(buf, &buf[2], trfLen - 2);
lawliet 17:f22357c94c81 391 trfLen -= 2;
lawliet 17:f22357c94c81 392 } else {
lawliet 17:f22357c94c81 393 break;
donatien 0:2ccb9960a044 394 }
donatien 0:2ccb9960a044 395
donatien 0:2ccb9960a044 396 }
donatien 0:2ccb9960a044 397
lawliet 17:f22357c94c81 398 m_sock.close();
lawliet 17:f22357c94c81 399 DBG("Completed HTTP transaction");
donatien 0:2ccb9960a044 400
lawliet 17:f22357c94c81 401 return HTTP_OK;
donatien 0:2ccb9960a044 402 }
donatien 0:2ccb9960a044 403
donatien 11:390362de8c3f 404 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure
donatien 0:2ccb9960a044 405 {
lawliet 17:f22357c94c81 406 return HTTP_OK;
donatien 7:4e39864f7b15 407 }
donatien 7:4e39864f7b15 408
donatien 11:390362de8c3f 409 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure
donatien 7:4e39864f7b15 410 {
lawliet 17:f22357c94c81 411 return HTTP_OK;
donatien 0:2ccb9960a044 412 }
donatien 0:2ccb9960a044 413
donatien 11:390362de8c3f 414 HTTPResult HTTPClient::parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen) //Parse URL
donatien 0:2ccb9960a044 415 {
lawliet 17:f22357c94c81 416 char* schemePtr = (char*) url;
lawliet 17:f22357c94c81 417 char* hostPtr = (char*) strstr(url, "://");
lawliet 17:f22357c94c81 418 if(hostPtr == NULL) {
lawliet 17:f22357c94c81 419 WARN("Could not find host");
lawliet 17:f22357c94c81 420 return HTTP_PARSE; //URL is invalid
lawliet 17:f22357c94c81 421 }
lawliet 17:f22357c94c81 422
lawliet 17:f22357c94c81 423 if( maxSchemeLen < hostPtr - schemePtr + 1 ) { //including NULL-terminating char
lawliet 17:f22357c94c81 424 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
lawliet 17:f22357c94c81 425 return HTTP_PARSE;
lawliet 17:f22357c94c81 426 }
lawliet 17:f22357c94c81 427 memcpy(scheme, schemePtr, hostPtr - schemePtr);
lawliet 17:f22357c94c81 428 scheme[hostPtr - schemePtr] = '\0';
donatien 0:2ccb9960a044 429
lawliet 17:f22357c94c81 430 hostPtr+=3;
donatien 0:2ccb9960a044 431
lawliet 17:f22357c94c81 432 size_t hostLen = 0;
donatien 0:2ccb9960a044 433
lawliet 17:f22357c94c81 434 char* portPtr = strchr(hostPtr, ':');
lawliet 17:f22357c94c81 435 if( portPtr != NULL ) {
lawliet 17:f22357c94c81 436 hostLen = portPtr - hostPtr;
lawliet 17:f22357c94c81 437 portPtr++;
lawliet 17:f22357c94c81 438 if( sscanf(portPtr, "%hu", port) != 1) {
lawliet 17:f22357c94c81 439 WARN("Could not find port");
lawliet 17:f22357c94c81 440 return HTTP_PARSE;
lawliet 17:f22357c94c81 441 }
lawliet 17:f22357c94c81 442 } else {
lawliet 17:f22357c94c81 443 *port=0;
donatien 0:2ccb9960a044 444 }
lawliet 17:f22357c94c81 445 char* pathPtr = strchr(hostPtr, '/');
lawliet 17:f22357c94c81 446 if( hostLen == 0 ) {
lawliet 17:f22357c94c81 447 hostLen = pathPtr - hostPtr;
lawliet 17:f22357c94c81 448 }
donatien 0:2ccb9960a044 449
lawliet 17:f22357c94c81 450 if( maxHostLen < hostLen + 1 ) { //including NULL-terminating char
lawliet 17:f22357c94c81 451 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
lawliet 17:f22357c94c81 452 return HTTP_PARSE;
lawliet 17:f22357c94c81 453 }
lawliet 17:f22357c94c81 454 memcpy(host, hostPtr, hostLen);
lawliet 17:f22357c94c81 455 host[hostLen] = '\0';
donatien 0:2ccb9960a044 456
lawliet 17:f22357c94c81 457 size_t pathLen;
lawliet 17:f22357c94c81 458 char* fragmentPtr = strchr(hostPtr, '#');
lawliet 17:f22357c94c81 459 if(fragmentPtr != NULL) {
lawliet 17:f22357c94c81 460 pathLen = fragmentPtr - pathPtr;
lawliet 17:f22357c94c81 461 } else {
lawliet 17:f22357c94c81 462 pathLen = strlen(pathPtr);
lawliet 17:f22357c94c81 463 }
donatien 0:2ccb9960a044 464
lawliet 17:f22357c94c81 465 if( maxPathLen < pathLen + 1 ) { //including NULL-terminating char
lawliet 17:f22357c94c81 466 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
lawliet 17:f22357c94c81 467 return HTTP_PARSE;
lawliet 17:f22357c94c81 468 }
lawliet 17:f22357c94c81 469 memcpy(path, pathPtr, pathLen);
lawliet 17:f22357c94c81 470 path[pathLen] = '\0';
donatien 0:2ccb9960a044 471
lawliet 17:f22357c94c81 472 return HTTP_OK;
donatien 0:2ccb9960a044 473 }