iSDIO Library for TOSHIBA FlashAir. include HTTP or HTTPS Client.

Dependencies:   SDFileSystem

Dependents:   FlashAir_Twitter Neon_F303K8_04

Fork of HTTPClient by Donatien Garnier

Committer:
ban4jp
Date:
Mon Dec 15 12:23:22 2014 +0000
Revision:
20:51abf34bcc06
Parent:
19:3b1625dbd7e9
Initial commit.

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
ban4jp 20:51abf34bcc06 21 #if 1
donatien 12:89d09a6db00a 22 //Enable debug
donatien 11:390362de8c3f 23 #include <cstdio>
ban4jp 19:3b1625dbd7e9 24 #define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__);
ban4jp 19:3b1625dbd7e9 25 #define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__);
ban4jp 19:3b1625dbd7e9 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
ban4jp 19:3b1625dbd7e9 30 #define DBG(x, ...)
donatien 12:89d09a6db00a 31 #define WARN(x, ...)
ban4jp 19:3b1625dbd7e9 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
donatien 0:2ccb9960a044 43 #define CHUNK_SIZE 256
ban4jp 20:51abf34bcc06 44 #define HEADER_KEY_MAXLENGTH 64
ban4jp 20:51abf34bcc06 45 #define HEADER_VALUE_MAXLENGTH 128
donatien 0:2ccb9960a044 46
donatien 0:2ccb9960a044 47 #include <cstring>
donatien 0:2ccb9960a044 48
donatien 11:390362de8c3f 49 #include "HTTPClient.h"
donatien 11:390362de8c3f 50
donatien 0:2ccb9960a044 51 HTTPClient::HTTPClient() :
ban4jp 20:51abf34bcc06 52 m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
donatien 0:2ccb9960a044 53 {
ban4jp 20:51abf34bcc06 54 bufferPos = buffer;
ban4jp 20:51abf34bcc06 55 recvCount = 0;
donatien 0:2ccb9960a044 56 }
donatien 0:2ccb9960a044 57
donatien 0:2ccb9960a044 58 HTTPClient::~HTTPClient()
donatien 0:2ccb9960a044 59 {
donatien 0:2ccb9960a044 60
donatien 0:2ccb9960a044 61 }
donatien 0:2ccb9960a044 62
donatien 0:2ccb9960a044 63 #if 0
donatien 0:2ccb9960a044 64 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
donatien 0:2ccb9960a044 65 {
ban4jp 19:3b1625dbd7e9 66 m_basicAuthUser = user;
ban4jp 19:3b1625dbd7e9 67 m_basicAuthPassword = password;
donatien 0:2ccb9960a044 68 }
donatien 0:2ccb9960a044 69 #endif
donatien 0:2ccb9960a044 70
donatien 12:89d09a6db00a 71 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 0:2ccb9960a044 72 {
ban4jp 19:3b1625dbd7e9 73 return connect(url, HTTP_GET, NULL, pDataIn, timeout);
donatien 0:2ccb9960a044 74 }
donatien 0:2ccb9960a044 75
donatien 12:89d09a6db00a 76 HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 0:2ccb9960a044 77 {
ban4jp 19:3b1625dbd7e9 78 HTTPText str(result, maxResultLen);
ban4jp 19:3b1625dbd7e9 79 return get(url, &str, timeout);
donatien 0:2ccb9960a044 80 }
donatien 0:2ccb9960a044 81
donatien 12:89d09a6db00a 82 HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 0:2ccb9960a044 83 {
ban4jp 19:3b1625dbd7e9 84 return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
donatien 0:2ccb9960a044 85 }
donatien 0:2ccb9960a044 86
donatien 16:1f743885e7de 87 HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 16:1f743885e7de 88 {
ban4jp 19:3b1625dbd7e9 89 return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
donatien 16:1f743885e7de 90 }
donatien 16:1f743885e7de 91
donatien 16:1f743885e7de 92 HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
donatien 16:1f743885e7de 93 {
ban4jp 19:3b1625dbd7e9 94 return connect(url, HTTP_DELETE, NULL, pDataIn, timeout);
donatien 16:1f743885e7de 95 }
donatien 16:1f743885e7de 96
donatien 16:1f743885e7de 97
donatien 0:2ccb9960a044 98 int HTTPClient::getHTTPResponseCode()
donatien 0:2ccb9960a044 99 {
ban4jp 19:3b1625dbd7e9 100 return m_httpResponseCode;
donatien 0:2ccb9960a044 101 }
donatien 0:2ccb9960a044 102
donatien 5:791fc3dcb6c4 103 #define CHECK_CONN_ERR(ret) \
donatien 5:791fc3dcb6c4 104 do{ \
donatien 7:4e39864f7b15 105 if(ret) { \
donatien 5:791fc3dcb6c4 106 ERR("Connection error (%d)", ret); \
donatien 11:390362de8c3f 107 return HTTP_CONN; \
donatien 5:791fc3dcb6c4 108 } \
donatien 5:791fc3dcb6c4 109 } while(0)
donatien 5:791fc3dcb6c4 110
donatien 5:791fc3dcb6c4 111 #define PRTCL_ERR() \
donatien 5:791fc3dcb6c4 112 do{ \
donatien 5:791fc3dcb6c4 113 ERR("Protocol error"); \
donatien 11:390362de8c3f 114 return HTTP_PRTCL; \
donatien 5:791fc3dcb6c4 115 } while(0)
donatien 0:2ccb9960a044 116
donatien 12:89d09a6db00a 117 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request
ban4jp 19:3b1625dbd7e9 118 {
ban4jp 19:3b1625dbd7e9 119 m_httpResponseCode = 0; //Invalidate code
ban4jp 19:3b1625dbd7e9 120 m_timeout = timeout;
ban4jp 19:3b1625dbd7e9 121
ban4jp 19:3b1625dbd7e9 122 pDataIn->writeReset();
ban4jp 19:3b1625dbd7e9 123 if( pDataOut ) {
ban4jp 19:3b1625dbd7e9 124 pDataOut->readReset();
ban4jp 19:3b1625dbd7e9 125 }
donatien 0:2ccb9960a044 126
ban4jp 19:3b1625dbd7e9 127 char scheme[8];
ban4jp 19:3b1625dbd7e9 128 uint16_t port;
ban4jp 20:51abf34bcc06 129 uint16_t cmd;
ban4jp 19:3b1625dbd7e9 130 char host[32];
ban4jp 19:3b1625dbd7e9 131 char path[64];
ban4jp 19:3b1625dbd7e9 132 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?)
ban4jp 19:3b1625dbd7e9 133 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
ban4jp 19:3b1625dbd7e9 134 if(res != HTTP_OK) {
ban4jp 19:3b1625dbd7e9 135 ERR("parseURL returned %d", res);
ban4jp 19:3b1625dbd7e9 136 return res;
ban4jp 19:3b1625dbd7e9 137 }
donatien 0:2ccb9960a044 138
ban4jp 19:3b1625dbd7e9 139 if(port == 0) { //TODO do handle HTTPS->443
ban4jp 19:3b1625dbd7e9 140 port = 80;
ban4jp 19:3b1625dbd7e9 141 }
ban4jp 20:51abf34bcc06 142 if(strcmp(scheme, "http") == 0) {
ban4jp 20:51abf34bcc06 143 cmd = 0x21; //SendHTTPMessageByRegister
ban4jp 20:51abf34bcc06 144 } else if(strcmp(scheme, "https") == 0) {
ban4jp 20:51abf34bcc06 145 cmd = 0x23; //SendHTTPSSLMessageByRegister
ban4jp 20:51abf34bcc06 146 } else {
ban4jp 20:51abf34bcc06 147 ERR("Not support scheme %s", scheme);
ban4jp 20:51abf34bcc06 148 return HTTP_PARSE;
ban4jp 20:51abf34bcc06 149 }
donatien 0:2ccb9960a044 150
ban4jp 19:3b1625dbd7e9 151 DBG("Scheme: %s", scheme);
ban4jp 19:3b1625dbd7e9 152 DBG("Host: %s", host);
ban4jp 19:3b1625dbd7e9 153 DBG("Port: %d", port);
ban4jp 20:51abf34bcc06 154 DBG("Cmd: %x", cmd);
ban4jp 19:3b1625dbd7e9 155 DBG("Path: %s", path);
donatien 0:2ccb9960a044 156
ban4jp 20:51abf34bcc06 157 int ret;
ban4jp 20:51abf34bcc06 158
ban4jp 20:51abf34bcc06 159 //Get card instance
ban4jp 20:51abf34bcc06 160 card = SD_iSDIO::getInstance();
ban4jp 20:51abf34bcc06 161 sequenceId = card->getSequenceId();
ban4jp 20:51abf34bcc06 162
ban4jp 20:51abf34bcc06 163 //Create card command
ban4jp 20:51abf34bcc06 164 memset(buffer, 0, 1024);
ban4jp 20:51abf34bcc06 165 bufferPos = buffer;
ban4jp 20:51abf34bcc06 166 bufferPos = put_command_header(bufferPos, 1, 0);
ban4jp 20:51abf34bcc06 167 bufferPos = put_command_info_header(bufferPos, cmd, sequenceId, 2);
ban4jp 20:51abf34bcc06 168 bufferPos = put_str_arg(bufferPos, host);
ban4jp 20:51abf34bcc06 169
ban4jp 20:51abf34bcc06 170 uint8_t* bodyLenPos = bufferPos;
ban4jp 20:51abf34bcc06 171 bufferPos += 4; //skip value of data size
donatien 0:2ccb9960a044 172
ban4jp 19:3b1625dbd7e9 173 //Send request
ban4jp 19:3b1625dbd7e9 174 DBG("Sending request");
ban4jp 19:3b1625dbd7e9 175 char buf[CHUNK_SIZE];
ban4jp 19:3b1625dbd7e9 176 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":"";
ban4jp 19:3b1625dbd7e9 177 snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request
ban4jp 19:3b1625dbd7e9 178 ret = send(buf);
ban4jp 19:3b1625dbd7e9 179 if(ret) {
ban4jp 19:3b1625dbd7e9 180 ERR("Could not write request");
ban4jp 19:3b1625dbd7e9 181 return HTTP_CONN;
donatien 0:2ccb9960a044 182 }
ban4jp 19:3b1625dbd7e9 183
ban4jp 19:3b1625dbd7e9 184 //Send all headers
ban4jp 19:3b1625dbd7e9 185
ban4jp 19:3b1625dbd7e9 186 //Send default headers
ban4jp 19:3b1625dbd7e9 187 DBG("Sending headers");
ban4jp 19:3b1625dbd7e9 188 if( pDataOut != NULL ) {
ban4jp 19:3b1625dbd7e9 189 if( pDataOut->getIsChunked() ) {
ban4jp 19:3b1625dbd7e9 190 ret = send("Transfer-Encoding: chunked\r\n");
ban4jp 19:3b1625dbd7e9 191 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 192 } else {
ban4jp 19:3b1625dbd7e9 193 snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen());
ban4jp 19:3b1625dbd7e9 194 ret = send(buf);
ban4jp 19:3b1625dbd7e9 195 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 196 }
ban4jp 19:3b1625dbd7e9 197 char type[48];
ban4jp 19:3b1625dbd7e9 198 if( pDataOut->getDataType(type, 48) == HTTP_OK ) {
ban4jp 19:3b1625dbd7e9 199 snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type);
ban4jp 19:3b1625dbd7e9 200 ret = send(buf);
ban4jp 19:3b1625dbd7e9 201 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 202 }
ban4jp 19:3b1625dbd7e9 203
ban4jp 19:3b1625dbd7e9 204 //Send specific headers
ban4jp 19:3b1625dbd7e9 205 while( pDataOut->getHeader(buf, sizeof(buf) - 3) ) { //must have space left for CRLF + 0 terminating char
ban4jp 19:3b1625dbd7e9 206 size_t headerlen = strlen(buf);
ban4jp 19:3b1625dbd7e9 207 snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n");
ban4jp 19:3b1625dbd7e9 208 ret = send(buf);
ban4jp 19:3b1625dbd7e9 209 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 210 }
donatien 17:679e15a3d3db 211 }
ban4jp 19:3b1625dbd7e9 212
ban4jp 19:3b1625dbd7e9 213 //Send specific headers
ban4jp 19:3b1625dbd7e9 214 while( pDataIn->getHeader(buf, sizeof(buf) - 3) ) {
ban4jp 19:3b1625dbd7e9 215 size_t headerlen = strlen(buf);
ban4jp 19:3b1625dbd7e9 216 snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n");
ban4jp 19:3b1625dbd7e9 217 ret = send(buf);
ban4jp 19:3b1625dbd7e9 218 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 219 }
donatien 0:2ccb9960a044 220
ban4jp 19:3b1625dbd7e9 221 //Close headers
ban4jp 19:3b1625dbd7e9 222 DBG("Headers sent");
ban4jp 19:3b1625dbd7e9 223 ret = send("\r\n");
ban4jp 19:3b1625dbd7e9 224 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 225
ban4jp 19:3b1625dbd7e9 226 size_t trfLen;
donatien 0:2ccb9960a044 227
ban4jp 19:3b1625dbd7e9 228 //Send data (if available)
ban4jp 19:3b1625dbd7e9 229 if( pDataOut != NULL ) {
ban4jp 19:3b1625dbd7e9 230 DBG("Sending data");
ban4jp 19:3b1625dbd7e9 231 while(true) {
ban4jp 19:3b1625dbd7e9 232 size_t writtenLen = 0;
ban4jp 19:3b1625dbd7e9 233 pDataOut->read(buf, CHUNK_SIZE, &trfLen);
ban4jp 19:3b1625dbd7e9 234 if( pDataOut->getIsChunked() ) {
ban4jp 19:3b1625dbd7e9 235 //Write chunk header
ban4jp 19:3b1625dbd7e9 236 char chunkHeader[16];
ban4jp 19:3b1625dbd7e9 237 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
ban4jp 19:3b1625dbd7e9 238 ret = send(chunkHeader);
ban4jp 19:3b1625dbd7e9 239 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 240 } else if( trfLen == 0 ) {
ban4jp 19:3b1625dbd7e9 241 break;
ban4jp 19:3b1625dbd7e9 242 }
ban4jp 19:3b1625dbd7e9 243 if( trfLen != 0 ) {
ban4jp 19:3b1625dbd7e9 244 ret = send(buf, trfLen);
ban4jp 19:3b1625dbd7e9 245 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 246 }
donatien 0:2ccb9960a044 247
ban4jp 19:3b1625dbd7e9 248 if( pDataOut->getIsChunked() ) {
ban4jp 19:3b1625dbd7e9 249 ret = send("\r\n"); //Chunk-terminating CRLF
ban4jp 19:3b1625dbd7e9 250 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 251 } else {
ban4jp 19:3b1625dbd7e9 252 writtenLen += trfLen;
ban4jp 19:3b1625dbd7e9 253 if( writtenLen >= pDataOut->getDataLen() ) {
ban4jp 19:3b1625dbd7e9 254 break;
ban4jp 19:3b1625dbd7e9 255 }
ban4jp 19:3b1625dbd7e9 256 }
ban4jp 19:3b1625dbd7e9 257
ban4jp 19:3b1625dbd7e9 258 if( trfLen == 0 ) {
ban4jp 19:3b1625dbd7e9 259 break;
ban4jp 19:3b1625dbd7e9 260 }
ban4jp 19:3b1625dbd7e9 261 }
donatien 0:2ccb9960a044 262 }
donatien 0:2ccb9960a044 263
ban4jp 20:51abf34bcc06 264 put_u32(bodyLenPos, (bufferPos - bodyLenPos - 4));
ban4jp 20:51abf34bcc06 265 put_command_header(buffer, 1, (bufferPos - buffer));
ban4jp 20:51abf34bcc06 266
ban4jp 20:51abf34bcc06 267 #if 0
ban4jp 20:51abf34bcc06 268 for (int i = 0; i < 0x400; i++) {
ban4jp 20:51abf34bcc06 269 printf("%2x ", buffer[i]);
ban4jp 20:51abf34bcc06 270 if ((i & 0xf) == 0xf) printf("\n");
ban4jp 20:51abf34bcc06 271 if (i == 0x200-1) printf("----\n");
ban4jp 20:51abf34bcc06 272 }
ban4jp 20:51abf34bcc06 273 printf((char *)bodyLenPos + 4);
ban4jp 20:51abf34bcc06 274 printf("\n");
ban4jp 20:51abf34bcc06 275 #endif
ban4jp 20:51abf34bcc06 276
ban4jp 20:51abf34bcc06 277 DBG("Send data size %d", (bufferPos - buffer));
ban4jp 20:51abf34bcc06 278
ban4jp 20:51abf34bcc06 279 if( card->writeExtDataPort(1, 1, 0x000, buffer) != true ) {
ban4jp 20:51abf34bcc06 280 ERR("writeExtDataPort error (1)\n");
ban4jp 20:51abf34bcc06 281 return HTTP_PRTCL;
ban4jp 20:51abf34bcc06 282 }
ban4jp 20:51abf34bcc06 283 if( (bufferPos - buffer) > 512 ) {
ban4jp 20:51abf34bcc06 284 if( card->writeExtDataPort(1, 1, 0x000, &buffer[512]) != true ) {
ban4jp 20:51abf34bcc06 285 ERR("writeExtDataPort error (2)\n");
ban4jp 20:51abf34bcc06 286 return HTTP_PRTCL;
ban4jp 20:51abf34bcc06 287 }
ban4jp 20:51abf34bcc06 288 }
ban4jp 20:51abf34bcc06 289
ban4jp 20:51abf34bcc06 290 DBG("waitResponse");
ban4jp 20:51abf34bcc06 291 card->waitResponse(sequenceId);
ban4jp 20:51abf34bcc06 292
ban4jp 20:51abf34bcc06 293 bufferPos = buffer;
ban4jp 20:51abf34bcc06 294 recvCount = 0;
ban4jp 20:51abf34bcc06 295
ban4jp 19:3b1625dbd7e9 296 //Receive response
ban4jp 19:3b1625dbd7e9 297 DBG("Receiving response");
ban4jp 19:3b1625dbd7e9 298 ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
ban4jp 19:3b1625dbd7e9 299 CHECK_CONN_ERR(ret);
donatien 0:2ccb9960a044 300
ban4jp 19:3b1625dbd7e9 301 buf[trfLen] = '\0';
donatien 0:2ccb9960a044 302
ban4jp 19:3b1625dbd7e9 303 //Make sure we got the first response line
ban4jp 19:3b1625dbd7e9 304 char* crlfPtr = NULL;
ban4jp 19:3b1625dbd7e9 305 while( true ) {
ban4jp 19:3b1625dbd7e9 306 crlfPtr = strstr(buf, "\r\n");
ban4jp 19:3b1625dbd7e9 307 if(crlfPtr == NULL) {
ban4jp 19:3b1625dbd7e9 308 if( trfLen < CHUNK_SIZE - 1 ) {
ban4jp 19:3b1625dbd7e9 309 size_t newTrfLen;
ban4jp 19:3b1625dbd7e9 310 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
ban4jp 19:3b1625dbd7e9 311 trfLen += newTrfLen;
ban4jp 19:3b1625dbd7e9 312 buf[trfLen] = '\0';
ban4jp 19:3b1625dbd7e9 313 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
ban4jp 19:3b1625dbd7e9 314 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 315 continue;
ban4jp 19:3b1625dbd7e9 316 } else {
ban4jp 19:3b1625dbd7e9 317 PRTCL_ERR();
ban4jp 19:3b1625dbd7e9 318 }
ban4jp 19:3b1625dbd7e9 319 }
ban4jp 19:3b1625dbd7e9 320 break;
ban4jp 19:3b1625dbd7e9 321 }
donatien 0:2ccb9960a044 322
ban4jp 19:3b1625dbd7e9 323 int crlfPos = crlfPtr - buf;
ban4jp 19:3b1625dbd7e9 324 buf[crlfPos] = '\0';
donatien 0:2ccb9960a044 325
ban4jp 19:3b1625dbd7e9 326 //Parse HTTP response
ban4jp 19:3b1625dbd7e9 327 //if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 )
ban4jp 19:3b1625dbd7e9 328 if(crlfPos > 13) {
ban4jp 19:3b1625dbd7e9 329 buf[13] = '\0';
ban4jp 19:3b1625dbd7e9 330 }
ban4jp 19:3b1625dbd7e9 331 if( sscanf(buf, "HTTP/%*d.%*d %d", &m_httpResponseCode) != 1 ) { //Kludge for newlib nano
ban4jp 19:3b1625dbd7e9 332 //Cannot match string, error
ban4jp 19:3b1625dbd7e9 333 ERR("Not a correct HTTP answer : %s\n", buf);
donatien 5:791fc3dcb6c4 334 PRTCL_ERR();
ban4jp 19:3b1625dbd7e9 335 }
ban4jp 19:3b1625dbd7e9 336
ban4jp 20:51abf34bcc06 337 //if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) ) {
ban4jp 20:51abf34bcc06 338 if( (m_httpResponseCode < 100) || (m_httpResponseCode >= 600) ) {
ban4jp 19:3b1625dbd7e9 339 //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers
ban4jp 19:3b1625dbd7e9 340 WARN("Response code %d", m_httpResponseCode);
ban4jp 19:3b1625dbd7e9 341 PRTCL_ERR();
donatien 0:2ccb9960a044 342 }
donatien 0:2ccb9960a044 343
ban4jp 19:3b1625dbd7e9 344 DBG("Reading headers");
donatien 0:2ccb9960a044 345
ban4jp 19:3b1625dbd7e9 346 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
ban4jp 19:3b1625dbd7e9 347 trfLen -= (crlfPos + 2);
donatien 0:2ccb9960a044 348
ban4jp 19:3b1625dbd7e9 349 size_t recvContentLength = 0;
ban4jp 19:3b1625dbd7e9 350 bool recvChunked = false;
ban4jp 19:3b1625dbd7e9 351 bool recvLengthUnknown = true;
ban4jp 19:3b1625dbd7e9 352 //Now get headers
ban4jp 19:3b1625dbd7e9 353 while( true ) {
ban4jp 19:3b1625dbd7e9 354 crlfPtr = strstr(buf, "\r\n");
ban4jp 19:3b1625dbd7e9 355 if(crlfPtr == NULL) {
ban4jp 19:3b1625dbd7e9 356 if( trfLen < CHUNK_SIZE - 1 ) {
ban4jp 19:3b1625dbd7e9 357 size_t newTrfLen;
ban4jp 19:3b1625dbd7e9 358 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
ban4jp 19:3b1625dbd7e9 359 trfLen += newTrfLen;
ban4jp 19:3b1625dbd7e9 360 buf[trfLen] = '\0';
ban4jp 19:3b1625dbd7e9 361 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
ban4jp 19:3b1625dbd7e9 362 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 363 continue;
ban4jp 19:3b1625dbd7e9 364 } else {
ban4jp 19:3b1625dbd7e9 365 PRTCL_ERR();
ban4jp 19:3b1625dbd7e9 366 }
ban4jp 19:3b1625dbd7e9 367 }
donatien 0:2ccb9960a044 368
ban4jp 19:3b1625dbd7e9 369 crlfPos = crlfPtr - buf;
donatien 17:679e15a3d3db 370
ban4jp 19:3b1625dbd7e9 371 if(crlfPos == 0) { //End of headers
ban4jp 19:3b1625dbd7e9 372 DBG("Headers read");
ban4jp 19:3b1625dbd7e9 373 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
ban4jp 19:3b1625dbd7e9 374 trfLen -= 2;
ban4jp 19:3b1625dbd7e9 375 break;
ban4jp 19:3b1625dbd7e9 376 }
ban4jp 19:3b1625dbd7e9 377
ban4jp 19:3b1625dbd7e9 378 buf[crlfPos] = '\0';
ban4jp 19:3b1625dbd7e9 379
ban4jp 20:51abf34bcc06 380 char key[HEADER_KEY_MAXLENGTH];
ban4jp 20:51abf34bcc06 381 char value[HEADER_VALUE_MAXLENGTH];
ban4jp 19:3b1625dbd7e9 382
ban4jp 19:3b1625dbd7e9 383 //key[31] = '\0';
ban4jp 19:3b1625dbd7e9 384 //value[31] = '\0';
donatien 4:c071b05ac026 385
ban4jp 20:51abf34bcc06 386 memset(key, 0, HEADER_KEY_MAXLENGTH);
ban4jp 20:51abf34bcc06 387 memset(value, 0, HEADER_VALUE_MAXLENGTH);
ban4jp 19:3b1625dbd7e9 388
ban4jp 19:3b1625dbd7e9 389 //int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
ban4jp 19:3b1625dbd7e9 390
ban4jp 19:3b1625dbd7e9 391 int n = 0;
ban4jp 19:3b1625dbd7e9 392
ban4jp 19:3b1625dbd7e9 393 char* keyEnd = strchr(buf, ':');
ban4jp 19:3b1625dbd7e9 394 if(keyEnd != NULL) {
ban4jp 19:3b1625dbd7e9 395 *keyEnd = '\0';
ban4jp 20:51abf34bcc06 396 if(strlen(buf) < HEADER_KEY_MAXLENGTH) {
ban4jp 19:3b1625dbd7e9 397 strcpy(key, buf);
ban4jp 19:3b1625dbd7e9 398 n++;
ban4jp 19:3b1625dbd7e9 399 char* valueStart = keyEnd + 2;
ban4jp 19:3b1625dbd7e9 400 if( (valueStart - buf) < crlfPos ) {
ban4jp 20:51abf34bcc06 401 if(strlen(valueStart) < HEADER_VALUE_MAXLENGTH) {
ban4jp 19:3b1625dbd7e9 402 strcpy(value, valueStart);
ban4jp 19:3b1625dbd7e9 403 n++;
ban4jp 19:3b1625dbd7e9 404 }
ban4jp 19:3b1625dbd7e9 405 }
ban4jp 19:3b1625dbd7e9 406 }
donatien 17:679e15a3d3db 407 }
ban4jp 19:3b1625dbd7e9 408 if ( n == 2 ) {
ban4jp 20:51abf34bcc06 409 DBG("Read header : %s: %s", key, value);
ban4jp 19:3b1625dbd7e9 410 if( !strcmp(key, "Content-Length") ) {
ban4jp 19:3b1625dbd7e9 411 sscanf(value, "%d", &recvContentLength);
ban4jp 19:3b1625dbd7e9 412 recvLengthUnknown = false;
ban4jp 19:3b1625dbd7e9 413 pDataIn->setDataLen(recvContentLength);
ban4jp 19:3b1625dbd7e9 414 } else if( !strcmp(key, "Transfer-Encoding") ) {
ban4jp 19:3b1625dbd7e9 415 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) {
ban4jp 19:3b1625dbd7e9 416 recvChunked = true;
ban4jp 19:3b1625dbd7e9 417 recvLengthUnknown = false;
ban4jp 19:3b1625dbd7e9 418 pDataIn->setIsChunked(true);
ban4jp 19:3b1625dbd7e9 419 }
ban4jp 19:3b1625dbd7e9 420 } else if( !strcmp(key, "Content-Type") ) {
ban4jp 19:3b1625dbd7e9 421 pDataIn->setDataType(value);
ban4jp 19:3b1625dbd7e9 422 }
ban4jp 19:3b1625dbd7e9 423
ban4jp 19:3b1625dbd7e9 424 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
ban4jp 19:3b1625dbd7e9 425 trfLen -= (crlfPos + 2);
ban4jp 19:3b1625dbd7e9 426
ban4jp 19:3b1625dbd7e9 427 } else {
ban4jp 19:3b1625dbd7e9 428 ERR("Could not parse header");
ban4jp 19:3b1625dbd7e9 429 PRTCL_ERR();
donatien 0:2ccb9960a044 430 }
donatien 0:2ccb9960a044 431
donatien 0:2ccb9960a044 432 }
donatien 0:2ccb9960a044 433
ban4jp 19:3b1625dbd7e9 434 //Receive data
ban4jp 19:3b1625dbd7e9 435 DBG("Receiving data");
ban4jp 19:3b1625dbd7e9 436 while(true) {
ban4jp 19:3b1625dbd7e9 437 size_t readLen = 0;
donatien 0:2ccb9960a044 438
ban4jp 19:3b1625dbd7e9 439 if( recvChunked ) {
ban4jp 19:3b1625dbd7e9 440 //Read chunk header
ban4jp 19:3b1625dbd7e9 441 bool foundCrlf;
ban4jp 19:3b1625dbd7e9 442 do {
ban4jp 19:3b1625dbd7e9 443 foundCrlf = false;
ban4jp 19:3b1625dbd7e9 444 crlfPos=0;
ban4jp 19:3b1625dbd7e9 445 buf[trfLen]=0;
ban4jp 19:3b1625dbd7e9 446 if(trfLen >= 2) {
ban4jp 19:3b1625dbd7e9 447 for(; crlfPos < trfLen - 2; crlfPos++) {
ban4jp 19:3b1625dbd7e9 448 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) {
ban4jp 19:3b1625dbd7e9 449 foundCrlf = true;
ban4jp 19:3b1625dbd7e9 450 break;
ban4jp 19:3b1625dbd7e9 451 }
ban4jp 19:3b1625dbd7e9 452 }
ban4jp 19:3b1625dbd7e9 453 }
ban4jp 19:3b1625dbd7e9 454 if(!foundCrlf) { //Try to read more
ban4jp 19:3b1625dbd7e9 455 if( trfLen < CHUNK_SIZE ) {
ban4jp 19:3b1625dbd7e9 456 size_t newTrfLen;
ban4jp 19:3b1625dbd7e9 457 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
ban4jp 19:3b1625dbd7e9 458 trfLen += newTrfLen;
ban4jp 19:3b1625dbd7e9 459 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 460 continue;
ban4jp 19:3b1625dbd7e9 461 } else {
ban4jp 19:3b1625dbd7e9 462 PRTCL_ERR();
ban4jp 19:3b1625dbd7e9 463 }
ban4jp 19:3b1625dbd7e9 464 }
ban4jp 19:3b1625dbd7e9 465 } while(!foundCrlf);
ban4jp 19:3b1625dbd7e9 466 buf[crlfPos] = '\0';
ban4jp 19:3b1625dbd7e9 467 int n = sscanf(buf, "%x", &readLen);
ban4jp 19:3b1625dbd7e9 468 if(n!=1) {
ban4jp 19:3b1625dbd7e9 469 ERR("Could not read chunk length");
ban4jp 19:3b1625dbd7e9 470 PRTCL_ERR();
donatien 14:2744e0c0e527 471 }
ban4jp 19:3b1625dbd7e9 472
ban4jp 19:3b1625dbd7e9 473 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
ban4jp 19:3b1625dbd7e9 474 trfLen -= (crlfPos + 2);
ban4jp 19:3b1625dbd7e9 475
ban4jp 19:3b1625dbd7e9 476 if( readLen == 0 ) {
ban4jp 19:3b1625dbd7e9 477 //Last chunk
ban4jp 19:3b1625dbd7e9 478 break;
ban4jp 19:3b1625dbd7e9 479 }
ban4jp 19:3b1625dbd7e9 480 } else {
ban4jp 19:3b1625dbd7e9 481 readLen = recvContentLength;
donatien 0:2ccb9960a044 482 }
ban4jp 19:3b1625dbd7e9 483
ban4jp 19:3b1625dbd7e9 484 DBG("Retrieving %d bytes (%d bytes in buffer)", readLen, trfLen);
ban4jp 19:3b1625dbd7e9 485
ban4jp 19:3b1625dbd7e9 486 do {
ban4jp 19:3b1625dbd7e9 487 if(recvLengthUnknown ) {
ban4jp 19:3b1625dbd7e9 488 readLen = trfLen;
ban4jp 19:3b1625dbd7e9 489 }
ban4jp 19:3b1625dbd7e9 490 pDataIn->write(buf, MIN(trfLen, readLen));
ban4jp 19:3b1625dbd7e9 491 if(!recvLengthUnknown) {
ban4jp 19:3b1625dbd7e9 492 if( trfLen > readLen ) {
ban4jp 19:3b1625dbd7e9 493 memmove(buf, &buf[readLen], trfLen - readLen);
ban4jp 19:3b1625dbd7e9 494 trfLen -= readLen;
ban4jp 19:3b1625dbd7e9 495 readLen = 0;
ban4jp 19:3b1625dbd7e9 496 } else {
ban4jp 19:3b1625dbd7e9 497 readLen -= trfLen;
ban4jp 19:3b1625dbd7e9 498 }
ban4jp 19:3b1625dbd7e9 499 } else {
ban4jp 19:3b1625dbd7e9 500 trfLen = 0;
ban4jp 19:3b1625dbd7e9 501 }
ban4jp 19:3b1625dbd7e9 502
ban4jp 19:3b1625dbd7e9 503 if(readLen || recvLengthUnknown) {
ban4jp 19:3b1625dbd7e9 504 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
ban4jp 19:3b1625dbd7e9 505 if(recvLengthUnknown && (ret == HTTP_CLOSED)) {
ban4jp 19:3b1625dbd7e9 506 //Write and exit
ban4jp 19:3b1625dbd7e9 507 pDataIn->write(buf, trfLen);
ban4jp 19:3b1625dbd7e9 508 break;
ban4jp 19:3b1625dbd7e9 509 }
ban4jp 19:3b1625dbd7e9 510 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 511 if(recvLengthUnknown && (trfLen == 0)) {
ban4jp 19:3b1625dbd7e9 512 break;
ban4jp 19:3b1625dbd7e9 513 }
ban4jp 19:3b1625dbd7e9 514 }
ban4jp 19:3b1625dbd7e9 515 } while(readLen || recvLengthUnknown);
ban4jp 19:3b1625dbd7e9 516
ban4jp 19:3b1625dbd7e9 517 if( recvChunked ) {
ban4jp 19:3b1625dbd7e9 518 if(trfLen < 2) {
ban4jp 19:3b1625dbd7e9 519 size_t newTrfLen;
ban4jp 19:3b1625dbd7e9 520 //Read missing chars to find end of chunk
ban4jp 19:3b1625dbd7e9 521 ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen);
ban4jp 19:3b1625dbd7e9 522 CHECK_CONN_ERR(ret);
ban4jp 19:3b1625dbd7e9 523 trfLen += newTrfLen;
ban4jp 19:3b1625dbd7e9 524 }
ban4jp 19:3b1625dbd7e9 525 if( (buf[0] != '\r') || (buf[1] != '\n') ) {
ban4jp 19:3b1625dbd7e9 526 ERR("Format error");
ban4jp 19:3b1625dbd7e9 527 PRTCL_ERR();
ban4jp 19:3b1625dbd7e9 528 }
ban4jp 19:3b1625dbd7e9 529 memmove(buf, &buf[2], trfLen - 2);
ban4jp 19:3b1625dbd7e9 530 trfLen -= 2;
ban4jp 19:3b1625dbd7e9 531 } else {
ban4jp 19:3b1625dbd7e9 532 break;
donatien 0:2ccb9960a044 533 }
donatien 0:2ccb9960a044 534
donatien 0:2ccb9960a044 535 }
donatien 0:2ccb9960a044 536
ban4jp 19:3b1625dbd7e9 537 DBG("Completed HTTP transaction");
donatien 0:2ccb9960a044 538
ban4jp 19:3b1625dbd7e9 539 return HTTP_OK;
donatien 0:2ccb9960a044 540 }
donatien 0:2ccb9960a044 541
donatien 11:390362de8c3f 542 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure
donatien 0:2ccb9960a044 543 {
ban4jp 19:3b1625dbd7e9 544 DBG("Trying to read between %d and %d bytes", minLen, maxLen);
ban4jp 19:3b1625dbd7e9 545 size_t readLen = 0;
ban4jp 19:3b1625dbd7e9 546
ban4jp 20:51abf34bcc06 547 DBG(" recvCount: %d", recvCount);
ban4jp 20:51abf34bcc06 548
ban4jp 20:51abf34bcc06 549 if (recvCount == 0) {
ban4jp 19:3b1625dbd7e9 550
ban4jp 20:51abf34bcc06 551 // Read header and data.
ban4jp 20:51abf34bcc06 552 if (!card->readExtDataPort(1, 1, 0x200, buffer)) {
ban4jp 20:51abf34bcc06 553 return HTTP_PRTCL;
ban4jp 20:51abf34bcc06 554 }
ban4jp 20:51abf34bcc06 555 #if 0
ban4jp 20:51abf34bcc06 556 for (int i = 0; i < 0x200; i++) {
ban4jp 20:51abf34bcc06 557 printf("%2x ", buffer[i]);
ban4jp 20:51abf34bcc06 558 if ((i & 0xf) == 0xf) printf("\n");
ban4jp 20:51abf34bcc06 559 }
ban4jp 20:51abf34bcc06 560 #endif
ban4jp 20:51abf34bcc06 561 if (buffer[0] != 0x02) {
ban4jp 20:51abf34bcc06 562 return HTTP_CONN;
ban4jp 19:3b1625dbd7e9 563 }
ban4jp 19:3b1625dbd7e9 564
ban4jp 20:51abf34bcc06 565 recvTotalSize = get_u32(buffer + 20);
ban4jp 20:51abf34bcc06 566 uint32_t recvSize = recvTotalSize > 488 ? 488 : recvTotalSize;
ban4jp 20:51abf34bcc06 567 uint32_t pos = 24;
ban4jp 20:51abf34bcc06 568
ban4jp 20:51abf34bcc06 569 if (recvSize < maxLen) {
ban4jp 20:51abf34bcc06 570 memcpy(buf, &buffer[pos], recvSize);
ban4jp 20:51abf34bcc06 571 readLen = recvSize;
ban4jp 19:3b1625dbd7e9 572 } else {
ban4jp 20:51abf34bcc06 573 memcpy(buf, &buffer[pos], maxLen);
ban4jp 20:51abf34bcc06 574 readLen = maxLen;
ban4jp 20:51abf34bcc06 575 }
ban4jp 20:51abf34bcc06 576 bufferPos = &buffer[pos] + readLen;
ban4jp 20:51abf34bcc06 577 recvAvailableSize = recvTotalSize - readLen;
ban4jp 20:51abf34bcc06 578
ban4jp 20:51abf34bcc06 579 DBG(" recvTotalSize: %d", recvTotalSize);
ban4jp 20:51abf34bcc06 580 DBG(" recvAvailableSize: %d", recvAvailableSize);
ban4jp 20:51abf34bcc06 581
ban4jp 20:51abf34bcc06 582 recvCount++;
ban4jp 20:51abf34bcc06 583
ban4jp 20:51abf34bcc06 584 } else {
ban4jp 20:51abf34bcc06 585
ban4jp 20:51abf34bcc06 586 uint32_t recvSize = 512 - (bufferPos - buffer);
ban4jp 20:51abf34bcc06 587 if (recvAvailableSize < recvSize) recvSize = recvAvailableSize;
ban4jp 20:51abf34bcc06 588
ban4jp 20:51abf34bcc06 589 DBG(" recvAvailableSize: %d", recvAvailableSize);
ban4jp 20:51abf34bcc06 590 DBG(" recvSize: %d", recvSize);
ban4jp 20:51abf34bcc06 591
ban4jp 20:51abf34bcc06 592 if (recvSize > 0) {
ban4jp 20:51abf34bcc06 593
ban4jp 20:51abf34bcc06 594 if (recvSize < maxLen) {
ban4jp 20:51abf34bcc06 595 memcpy(buf, bufferPos, recvSize);
ban4jp 20:51abf34bcc06 596 readLen = recvSize;
ban4jp 19:3b1625dbd7e9 597 } else {
ban4jp 20:51abf34bcc06 598 memcpy(buf, bufferPos, maxLen);
ban4jp 20:51abf34bcc06 599 readLen = maxLen;
ban4jp 20:51abf34bcc06 600 }
ban4jp 20:51abf34bcc06 601 bufferPos += readLen;
ban4jp 20:51abf34bcc06 602 recvAvailableSize -= readLen;
ban4jp 20:51abf34bcc06 603
ban4jp 20:51abf34bcc06 604 } else if (recvAvailableSize > 0) {
ban4jp 20:51abf34bcc06 605
ban4jp 20:51abf34bcc06 606 // Read next data.
ban4jp 20:51abf34bcc06 607 if (!card->readExtDataPort(1, 1, 0x200, buffer)) {
ban4jp 20:51abf34bcc06 608 return HTTP_PRTCL;
ban4jp 19:3b1625dbd7e9 609 }
ban4jp 20:51abf34bcc06 610 #if 0
ban4jp 20:51abf34bcc06 611 for (int i = 0; i < 0x200; i++) {
ban4jp 20:51abf34bcc06 612 printf("%2x ", buffer[i]);
ban4jp 20:51abf34bcc06 613 if ((i & 0xf) == 0xf) printf("\n");
ban4jp 20:51abf34bcc06 614 }
ban4jp 20:51abf34bcc06 615 #endif
ban4jp 20:51abf34bcc06 616 recvSize = recvAvailableSize > 512 ? 512 : recvAvailableSize;
ban4jp 20:51abf34bcc06 617
ban4jp 20:51abf34bcc06 618 if (recvSize < maxLen) {
ban4jp 20:51abf34bcc06 619 memcpy(buf, buffer, recvSize);
ban4jp 20:51abf34bcc06 620 readLen = recvSize;
ban4jp 20:51abf34bcc06 621 } else {
ban4jp 20:51abf34bcc06 622 memcpy(buf, buffer, maxLen);
ban4jp 20:51abf34bcc06 623 readLen = maxLen;
ban4jp 20:51abf34bcc06 624 }
ban4jp 20:51abf34bcc06 625 bufferPos = buffer + readLen;
ban4jp 20:51abf34bcc06 626 recvAvailableSize -= readLen;
ban4jp 20:51abf34bcc06 627
ban4jp 20:51abf34bcc06 628 recvCount++;
ban4jp 20:51abf34bcc06 629
ban4jp 19:3b1625dbd7e9 630 }
ban4jp 19:3b1625dbd7e9 631
donatien 7:4e39864f7b15 632 }
ban4jp 20:51abf34bcc06 633
ban4jp 19:3b1625dbd7e9 634 DBG("Read %d bytes", readLen);
ban4jp 19:3b1625dbd7e9 635 *pReadLen = readLen;
ban4jp 19:3b1625dbd7e9 636 return HTTP_OK;
donatien 7:4e39864f7b15 637 }
donatien 7:4e39864f7b15 638
donatien 11:390362de8c3f 639 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure
donatien 7:4e39864f7b15 640 {
ban4jp 19:3b1625dbd7e9 641 if(len == 0) {
ban4jp 19:3b1625dbd7e9 642 len = strlen(buf);
ban4jp 19:3b1625dbd7e9 643 }
ban4jp 19:3b1625dbd7e9 644 DBG("Trying to write %d bytes", len);
ban4jp 19:3b1625dbd7e9 645 size_t writtenLen = 0;
ban4jp 19:3b1625dbd7e9 646
ban4jp 20:51abf34bcc06 647 if(((buffer + 1024) - bufferPos) >= len) {
ban4jp 20:51abf34bcc06 648 writtenLen = len;
ban4jp 20:51abf34bcc06 649 } else {
ban4jp 20:51abf34bcc06 650 writtenLen = ((buffer + 1024) - bufferPos);
ban4jp 19:3b1625dbd7e9 651 }
ban4jp 20:51abf34bcc06 652 memcpy(bufferPos, buf, writtenLen);
ban4jp 20:51abf34bcc06 653 bufferPos += writtenLen;
ban4jp 19:3b1625dbd7e9 654
ban4jp 19:3b1625dbd7e9 655 DBG("Written %d bytes", writtenLen);
ban4jp 19:3b1625dbd7e9 656 return HTTP_OK;
donatien 0:2ccb9960a044 657 }
donatien 0:2ccb9960a044 658
donatien 11:390362de8c3f 659 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 660 {
ban4jp 19:3b1625dbd7e9 661 char* schemePtr = (char*) url;
ban4jp 19:3b1625dbd7e9 662 char* hostPtr = (char*) strstr(url, "://");
ban4jp 19:3b1625dbd7e9 663 if(hostPtr == NULL) {
ban4jp 19:3b1625dbd7e9 664 WARN("Could not find host");
ban4jp 19:3b1625dbd7e9 665 return HTTP_PARSE; //URL is invalid
ban4jp 19:3b1625dbd7e9 666 }
ban4jp 19:3b1625dbd7e9 667
ban4jp 19:3b1625dbd7e9 668 if( maxSchemeLen < hostPtr - schemePtr + 1 ) { //including NULL-terminating char
ban4jp 19:3b1625dbd7e9 669 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
ban4jp 19:3b1625dbd7e9 670 return HTTP_PARSE;
ban4jp 19:3b1625dbd7e9 671 }
ban4jp 19:3b1625dbd7e9 672 memcpy(scheme, schemePtr, hostPtr - schemePtr);
ban4jp 19:3b1625dbd7e9 673 scheme[hostPtr - schemePtr] = '\0';
donatien 0:2ccb9960a044 674
ban4jp 19:3b1625dbd7e9 675 hostPtr+=3;
donatien 0:2ccb9960a044 676
ban4jp 19:3b1625dbd7e9 677 size_t hostLen = 0;
donatien 0:2ccb9960a044 678
ban4jp 19:3b1625dbd7e9 679 char* portPtr = strchr(hostPtr, ':');
ban4jp 19:3b1625dbd7e9 680 if( portPtr != NULL ) {
ban4jp 19:3b1625dbd7e9 681 hostLen = portPtr - hostPtr;
ban4jp 19:3b1625dbd7e9 682 portPtr++;
ban4jp 19:3b1625dbd7e9 683 if( sscanf(portPtr, "%hu", port) != 1) {
ban4jp 19:3b1625dbd7e9 684 WARN("Could not find port");
ban4jp 19:3b1625dbd7e9 685 return HTTP_PARSE;
ban4jp 19:3b1625dbd7e9 686 }
ban4jp 19:3b1625dbd7e9 687 } else {
ban4jp 19:3b1625dbd7e9 688 *port=0;
donatien 0:2ccb9960a044 689 }
ban4jp 19:3b1625dbd7e9 690 char* pathPtr = strchr(hostPtr, '/');
ban4jp 19:3b1625dbd7e9 691 if( hostLen == 0 ) {
ban4jp 19:3b1625dbd7e9 692 hostLen = pathPtr - hostPtr;
ban4jp 19:3b1625dbd7e9 693 }
donatien 0:2ccb9960a044 694
ban4jp 19:3b1625dbd7e9 695 if( maxHostLen < hostLen + 1 ) { //including NULL-terminating char
ban4jp 19:3b1625dbd7e9 696 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
ban4jp 19:3b1625dbd7e9 697 return HTTP_PARSE;
ban4jp 19:3b1625dbd7e9 698 }
ban4jp 19:3b1625dbd7e9 699 memcpy(host, hostPtr, hostLen);
ban4jp 19:3b1625dbd7e9 700 host[hostLen] = '\0';
donatien 0:2ccb9960a044 701
ban4jp 19:3b1625dbd7e9 702 size_t pathLen;
ban4jp 19:3b1625dbd7e9 703 char* fragmentPtr = strchr(hostPtr, '#');
ban4jp 19:3b1625dbd7e9 704 if(fragmentPtr != NULL) {
ban4jp 19:3b1625dbd7e9 705 pathLen = fragmentPtr - pathPtr;
ban4jp 19:3b1625dbd7e9 706 } else {
ban4jp 19:3b1625dbd7e9 707 pathLen = strlen(pathPtr);
ban4jp 19:3b1625dbd7e9 708 }
donatien 0:2ccb9960a044 709
ban4jp 19:3b1625dbd7e9 710 if( maxPathLen < pathLen + 1 ) { //including NULL-terminating char
ban4jp 19:3b1625dbd7e9 711 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
ban4jp 19:3b1625dbd7e9 712 return HTTP_PARSE;
ban4jp 19:3b1625dbd7e9 713 }
ban4jp 19:3b1625dbd7e9 714 memcpy(path, pathPtr, pathLen);
ban4jp 19:3b1625dbd7e9 715 path[pathLen] = '\0';
donatien 0:2ccb9960a044 716
ban4jp 19:3b1625dbd7e9 717 return HTTP_OK;
donatien 0:2ccb9960a044 718 }