10.1 Kombiniert die Übung 6.4 Wenn sich jemand nähert, Lauflicht einschalten mit dem Yahoo Weather Dienst, dass bei Unterwarnungen das Lauflicht eingeschaltet wird.

Dependencies:   EthernetInterface mbed-rtos mbed spxml

Fork of YahooWeather by smd.iotkit2.ch

Committer:
marcel1691
Date:
Sat Jan 17 14:11:01 2015 +0000
Revision:
1:2e29a33cd918
Child:
2:c9e058ee6f87
Beispiel fuer Verwendung der HTTP Methoden (GET, POST, PUT, DELETE)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcel1691 1:2e29a33cd918 1 /* HTTPClient.cpp */
marcel1691 1:2e29a33cd918 2 /* Copyright (C) 2012 mbed.org, MIT License
marcel1691 1:2e29a33cd918 3 *
marcel1691 1:2e29a33cd918 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
marcel1691 1:2e29a33cd918 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
marcel1691 1:2e29a33cd918 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
marcel1691 1:2e29a33cd918 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
marcel1691 1:2e29a33cd918 8 * furnished to do so, subject to the following conditions:
marcel1691 1:2e29a33cd918 9 *
marcel1691 1:2e29a33cd918 10 * The above copyright notice and this permission notice shall be included in all copies or
marcel1691 1:2e29a33cd918 11 * substantial portions of the Software.
marcel1691 1:2e29a33cd918 12 *
marcel1691 1:2e29a33cd918 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
marcel1691 1:2e29a33cd918 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
marcel1691 1:2e29a33cd918 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
marcel1691 1:2e29a33cd918 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
marcel1691 1:2e29a33cd918 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
marcel1691 1:2e29a33cd918 18 */
marcel1691 1:2e29a33cd918 19
marcel1691 1:2e29a33cd918 20 //Debug is disabled by default
marcel1691 1:2e29a33cd918 21 //#define DEBUG "HTCL"
marcel1691 1:2e29a33cd918 22 #include <cstdio>
marcel1691 1:2e29a33cd918 23 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
marcel1691 1:2e29a33cd918 24 #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
marcel1691 1:2e29a33cd918 25 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
marcel1691 1:2e29a33cd918 26 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
marcel1691 1:2e29a33cd918 27 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
marcel1691 1:2e29a33cd918 28 #else
marcel1691 1:2e29a33cd918 29 #define DBG(x, ...)
marcel1691 1:2e29a33cd918 30 #define WARN(x, ...)
marcel1691 1:2e29a33cd918 31 #define ERR(x, ...)
marcel1691 1:2e29a33cd918 32 #define INFO(x, ...)
marcel1691 1:2e29a33cd918 33 #endif
marcel1691 1:2e29a33cd918 34
marcel1691 1:2e29a33cd918 35 //#define HTTP_PORT 80
marcel1691 1:2e29a33cd918 36
marcel1691 1:2e29a33cd918 37 #define OK 0
marcel1691 1:2e29a33cd918 38
marcel1691 1:2e29a33cd918 39 #define MIN(x,y) (((x)<(y))?(x):(y))
marcel1691 1:2e29a33cd918 40 #define MAX(x,y) (((x)>(y))?(x):(y))
marcel1691 1:2e29a33cd918 41
marcel1691 1:2e29a33cd918 42 #define CHUNK_SIZE 256
marcel1691 1:2e29a33cd918 43 #define MAXLEN_VALUE 120 /* Max URL and Max Value for Name:Value */
marcel1691 1:2e29a33cd918 44
marcel1691 1:2e29a33cd918 45 #include <cstring>
marcel1691 1:2e29a33cd918 46
marcel1691 1:2e29a33cd918 47 #include "HTTPClient.h"
marcel1691 1:2e29a33cd918 48
marcel1691 1:2e29a33cd918 49 HTTPClient::HTTPClient() :
marcel1691 1:2e29a33cd918 50 m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL),
marcel1691 1:2e29a33cd918 51 m_nCustomHeaders(0), m_httpResponseCode(0),
marcel1691 1:2e29a33cd918 52 m_maxredirections(1), m_location(NULL)
marcel1691 1:2e29a33cd918 53 {
marcel1691 1:2e29a33cd918 54
marcel1691 1:2e29a33cd918 55 }
marcel1691 1:2e29a33cd918 56
marcel1691 1:2e29a33cd918 57 HTTPClient::~HTTPClient()
marcel1691 1:2e29a33cd918 58 {
marcel1691 1:2e29a33cd918 59
marcel1691 1:2e29a33cd918 60 }
marcel1691 1:2e29a33cd918 61
marcel1691 1:2e29a33cd918 62 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
marcel1691 1:2e29a33cd918 63 {
marcel1691 1:2e29a33cd918 64 #if 1
marcel1691 1:2e29a33cd918 65 if (m_basicAuthUser)
marcel1691 1:2e29a33cd918 66 free(m_basicAuthUser);
marcel1691 1:2e29a33cd918 67 m_basicAuthUser = (char *)malloc(strlen(user)+1);
marcel1691 1:2e29a33cd918 68 strcpy(m_basicAuthUser, user);
marcel1691 1:2e29a33cd918 69 if (m_basicAuthPassword)
marcel1691 1:2e29a33cd918 70 free(m_basicAuthPassword);
marcel1691 1:2e29a33cd918 71 m_basicAuthPassword = (char *)malloc(strlen(password)+1);
marcel1691 1:2e29a33cd918 72 strcpy(m_basicAuthPassword, password);
marcel1691 1:2e29a33cd918 73 #else
marcel1691 1:2e29a33cd918 74 m_basicAuthUser = user;
marcel1691 1:2e29a33cd918 75 m_basicAuthPassword = password;
marcel1691 1:2e29a33cd918 76 #endif
marcel1691 1:2e29a33cd918 77 }
marcel1691 1:2e29a33cd918 78
marcel1691 1:2e29a33cd918 79 void HTTPClient::customHeaders(const char **headers, size_t pairs)
marcel1691 1:2e29a33cd918 80 {
marcel1691 1:2e29a33cd918 81 m_customHeaders = headers;
marcel1691 1:2e29a33cd918 82 m_nCustomHeaders = pairs;
marcel1691 1:2e29a33cd918 83 }
marcel1691 1:2e29a33cd918 84
marcel1691 1:2e29a33cd918 85
marcel1691 1:2e29a33cd918 86 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 87 {
marcel1691 1:2e29a33cd918 88 return connect(url, HTTP_GET, NULL, pDataIn, timeout);
marcel1691 1:2e29a33cd918 89 }
marcel1691 1:2e29a33cd918 90
marcel1691 1:2e29a33cd918 91 HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 92 {
marcel1691 1:2e29a33cd918 93 HTTPText str(result, maxResultLen);
marcel1691 1:2e29a33cd918 94 return get(url, &str, timeout);
marcel1691 1:2e29a33cd918 95 }
marcel1691 1:2e29a33cd918 96
marcel1691 1:2e29a33cd918 97 HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 98 {
marcel1691 1:2e29a33cd918 99 return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
marcel1691 1:2e29a33cd918 100 }
marcel1691 1:2e29a33cd918 101
marcel1691 1:2e29a33cd918 102 HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 103 {
marcel1691 1:2e29a33cd918 104 return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
marcel1691 1:2e29a33cd918 105 }
marcel1691 1:2e29a33cd918 106
marcel1691 1:2e29a33cd918 107 HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
marcel1691 1:2e29a33cd918 108 {
marcel1691 1:2e29a33cd918 109 return connect(url, HTTP_DELETE, NULL, pDataIn, timeout);
marcel1691 1:2e29a33cd918 110 }
marcel1691 1:2e29a33cd918 111
marcel1691 1:2e29a33cd918 112
marcel1691 1:2e29a33cd918 113 int HTTPClient::getHTTPResponseCode()
marcel1691 1:2e29a33cd918 114 {
marcel1691 1:2e29a33cd918 115 return m_httpResponseCode;
marcel1691 1:2e29a33cd918 116 }
marcel1691 1:2e29a33cd918 117
marcel1691 1:2e29a33cd918 118 void HTTPClient::setMaxRedirections(int i)
marcel1691 1:2e29a33cd918 119 {
marcel1691 1:2e29a33cd918 120 if (i < 1)
marcel1691 1:2e29a33cd918 121 i = 1;
marcel1691 1:2e29a33cd918 122 m_maxredirections = i;
marcel1691 1:2e29a33cd918 123 }
marcel1691 1:2e29a33cd918 124
marcel1691 1:2e29a33cd918 125 #define CHECK_CONN_ERR(ret) \
marcel1691 1:2e29a33cd918 126 do{ \
marcel1691 1:2e29a33cd918 127 if(ret) { \
marcel1691 1:2e29a33cd918 128 m_sock.close(); \
marcel1691 1:2e29a33cd918 129 ERR("Connection error (%d)", ret); \
marcel1691 1:2e29a33cd918 130 return HTTP_CONN; \
marcel1691 1:2e29a33cd918 131 } \
marcel1691 1:2e29a33cd918 132 } while(0)
marcel1691 1:2e29a33cd918 133
marcel1691 1:2e29a33cd918 134 #define PRTCL_ERR() \
marcel1691 1:2e29a33cd918 135 do{ \
marcel1691 1:2e29a33cd918 136 m_sock.close(); \
marcel1691 1:2e29a33cd918 137 ERR("Protocol error"); \
marcel1691 1:2e29a33cd918 138 return HTTP_PRTCL; \
marcel1691 1:2e29a33cd918 139 } while(0)
marcel1691 1:2e29a33cd918 140
marcel1691 1:2e29a33cd918 141 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request
marcel1691 1:2e29a33cd918 142 {
marcel1691 1:2e29a33cd918 143 m_httpResponseCode = 0; //Invalidate code
marcel1691 1:2e29a33cd918 144 m_timeout = timeout;
marcel1691 1:2e29a33cd918 145
marcel1691 1:2e29a33cd918 146 pDataIn->writeReset();
marcel1691 1:2e29a33cd918 147 if( pDataOut ) {
marcel1691 1:2e29a33cd918 148 pDataOut->readReset();
marcel1691 1:2e29a33cd918 149 }
marcel1691 1:2e29a33cd918 150
marcel1691 1:2e29a33cd918 151 char scheme[8];
marcel1691 1:2e29a33cd918 152 uint16_t port;
marcel1691 1:2e29a33cd918 153 char host[32];
marcel1691 1:2e29a33cd918 154 char path[MAXLEN_VALUE];
marcel1691 1:2e29a33cd918 155 size_t recvContentLength = 0;
marcel1691 1:2e29a33cd918 156 bool recvChunked = false;
marcel1691 1:2e29a33cd918 157 int crlfPos = 0;
marcel1691 1:2e29a33cd918 158 char buf[CHUNK_SIZE];
marcel1691 1:2e29a33cd918 159 size_t trfLen;
marcel1691 1:2e29a33cd918 160 int ret = 0;
marcel1691 1:2e29a33cd918 161
marcel1691 1:2e29a33cd918 162 int maxRedirect = m_maxredirections;
marcel1691 1:2e29a33cd918 163
marcel1691 1:2e29a33cd918 164 while (maxRedirect--) {
marcel1691 1:2e29a33cd918 165 bool takeRedirect = false;
marcel1691 1:2e29a33cd918 166
marcel1691 1:2e29a33cd918 167 INFO("parse: [%s]", url);
marcel1691 1:2e29a33cd918 168 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?)
marcel1691 1:2e29a33cd918 169 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
marcel1691 1:2e29a33cd918 170 if(res != HTTP_OK) {
marcel1691 1:2e29a33cd918 171 ERR("parseURL returned %d", res);
marcel1691 1:2e29a33cd918 172 return res;
marcel1691 1:2e29a33cd918 173 }
marcel1691 1:2e29a33cd918 174
marcel1691 1:2e29a33cd918 175 if(port == 0) { //TODO do handle HTTPS->443
marcel1691 1:2e29a33cd918 176 port = 80;
marcel1691 1:2e29a33cd918 177 }
marcel1691 1:2e29a33cd918 178
marcel1691 1:2e29a33cd918 179 DBG("Scheme: %s", scheme);
marcel1691 1:2e29a33cd918 180 DBG("Host: %s", host);
marcel1691 1:2e29a33cd918 181 DBG("Port: %d", port);
marcel1691 1:2e29a33cd918 182 DBG("Path: %s", path);
marcel1691 1:2e29a33cd918 183
marcel1691 1:2e29a33cd918 184 //Connect
marcel1691 1:2e29a33cd918 185 DBG("Connecting socket to server");
marcel1691 1:2e29a33cd918 186 ret = m_sock.connect(host, port);
marcel1691 1:2e29a33cd918 187 if (ret < 0) {
marcel1691 1:2e29a33cd918 188 m_sock.close();
marcel1691 1:2e29a33cd918 189 ERR("Could not connect");
marcel1691 1:2e29a33cd918 190 return HTTP_CONN;
marcel1691 1:2e29a33cd918 191 }
marcel1691 1:2e29a33cd918 192
marcel1691 1:2e29a33cd918 193 //Send request
marcel1691 1:2e29a33cd918 194 DBG("Sending request");
marcel1691 1:2e29a33cd918 195 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":"";
marcel1691 1:2e29a33cd918 196 snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s:%d\r\nConnection: keep-alive\r\n", meth, path, host, port); //Write request
marcel1691 1:2e29a33cd918 197 INFO(" buf{%s}", buf);
marcel1691 1:2e29a33cd918 198 ret = send(buf);
marcel1691 1:2e29a33cd918 199 if (ret) {
marcel1691 1:2e29a33cd918 200 m_sock.close();
marcel1691 1:2e29a33cd918 201 ERR("Could not write request");
marcel1691 1:2e29a33cd918 202 return HTTP_CONN;
marcel1691 1:2e29a33cd918 203 }
marcel1691 1:2e29a33cd918 204
marcel1691 1:2e29a33cd918 205 // send authorization
marcel1691 1:2e29a33cd918 206 INFO("send auth (if defined)");
marcel1691 1:2e29a33cd918 207 if (m_basicAuthUser && m_basicAuthPassword) {
marcel1691 1:2e29a33cd918 208 strcpy(buf, "Authorization: Basic ");
marcel1691 1:2e29a33cd918 209 createauth(m_basicAuthUser, m_basicAuthPassword, buf+strlen(buf), sizeof(buf)-strlen(buf));
marcel1691 1:2e29a33cd918 210 strcat(buf, "\r\n");
marcel1691 1:2e29a33cd918 211 INFO(" (%s,%s) => (%s)", m_basicAuthUser, m_basicAuthPassword, buf);
marcel1691 1:2e29a33cd918 212 ret = send(buf);
marcel1691 1:2e29a33cd918 213 INFO(" ret = %d", ret);
marcel1691 1:2e29a33cd918 214 if(ret) {
marcel1691 1:2e29a33cd918 215 m_sock.close();
marcel1691 1:2e29a33cd918 216 ERR("Could not write request");
marcel1691 1:2e29a33cd918 217 return HTTP_CONN;
marcel1691 1:2e29a33cd918 218 }
marcel1691 1:2e29a33cd918 219 }
marcel1691 1:2e29a33cd918 220
marcel1691 1:2e29a33cd918 221 //Send all headers
marcel1691 1:2e29a33cd918 222 INFO("Send custom header(s) %d (if any)", m_nCustomHeaders);
marcel1691 1:2e29a33cd918 223 for (size_t nh = 0; nh < m_nCustomHeaders * 2; nh+=2) {
marcel1691 1:2e29a33cd918 224 INFO("hdr[%d] %s:", nh, m_customHeaders[nh]);
marcel1691 1:2e29a33cd918 225 INFO(" %s", m_customHeaders[nh+1]);
marcel1691 1:2e29a33cd918 226 snprintf(buf, sizeof(buf), "%s: %s\r\n", m_customHeaders[nh], m_customHeaders[nh+1]);
marcel1691 1:2e29a33cd918 227 ret = send(buf);
marcel1691 1:2e29a33cd918 228 if (ret) {
marcel1691 1:2e29a33cd918 229 ERR("closing");
marcel1691 1:2e29a33cd918 230 wait_ms(50);
marcel1691 1:2e29a33cd918 231 m_sock.close();
marcel1691 1:2e29a33cd918 232 ERR("Could not write request");
marcel1691 1:2e29a33cd918 233 return HTTP_CONN;
marcel1691 1:2e29a33cd918 234 }
marcel1691 1:2e29a33cd918 235 INFO(" hdr %d", ret);
marcel1691 1:2e29a33cd918 236 }
marcel1691 1:2e29a33cd918 237
marcel1691 1:2e29a33cd918 238 //Send default headers
marcel1691 1:2e29a33cd918 239 DBG("Sending headers");
marcel1691 1:2e29a33cd918 240 if( pDataOut != NULL ) {
marcel1691 1:2e29a33cd918 241 if( pDataOut->getIsChunked() ) {
marcel1691 1:2e29a33cd918 242 ret = send("Transfer-Encoding: chunked\r\n");
marcel1691 1:2e29a33cd918 243 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 244 } else {
marcel1691 1:2e29a33cd918 245 snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen());
marcel1691 1:2e29a33cd918 246 ret = send(buf);
marcel1691 1:2e29a33cd918 247 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 248 }
marcel1691 1:2e29a33cd918 249 char type[48];
marcel1691 1:2e29a33cd918 250 if( pDataOut->getDataType(type, 48) == HTTP_OK ) {
marcel1691 1:2e29a33cd918 251 snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type);
marcel1691 1:2e29a33cd918 252 ret = send(buf);
marcel1691 1:2e29a33cd918 253 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 254 }
marcel1691 1:2e29a33cd918 255 }
marcel1691 1:2e29a33cd918 256
marcel1691 1:2e29a33cd918 257 //Close headers
marcel1691 1:2e29a33cd918 258 DBG("Headers sent");
marcel1691 1:2e29a33cd918 259 ret = send("\r\n");
marcel1691 1:2e29a33cd918 260 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 261
marcel1691 1:2e29a33cd918 262 //Send data (if available)
marcel1691 1:2e29a33cd918 263 if( pDataOut != NULL ) {
marcel1691 1:2e29a33cd918 264 DBG("Sending data");
marcel1691 1:2e29a33cd918 265 while(true) {
marcel1691 1:2e29a33cd918 266 size_t writtenLen = 0;
marcel1691 1:2e29a33cd918 267 pDataOut->read(buf, CHUNK_SIZE, &trfLen);
marcel1691 1:2e29a33cd918 268 if( pDataOut->getIsChunked() ) {
marcel1691 1:2e29a33cd918 269 //Write chunk header
marcel1691 1:2e29a33cd918 270 char chunkHeader[16];
marcel1691 1:2e29a33cd918 271 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
marcel1691 1:2e29a33cd918 272 ret = send(chunkHeader);
marcel1691 1:2e29a33cd918 273 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 274 } else if( trfLen == 0 ) {
marcel1691 1:2e29a33cd918 275 break;
marcel1691 1:2e29a33cd918 276 }
marcel1691 1:2e29a33cd918 277 if( trfLen != 0 ) {
marcel1691 1:2e29a33cd918 278 ret = send(buf, trfLen);
marcel1691 1:2e29a33cd918 279 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 280 }
marcel1691 1:2e29a33cd918 281
marcel1691 1:2e29a33cd918 282 if( pDataOut->getIsChunked() ) {
marcel1691 1:2e29a33cd918 283 ret = send("\r\n"); //Chunk-terminating CRLF
marcel1691 1:2e29a33cd918 284 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 285 } else {
marcel1691 1:2e29a33cd918 286 writtenLen += trfLen;
marcel1691 1:2e29a33cd918 287 if( writtenLen >= pDataOut->getDataLen() ) {
marcel1691 1:2e29a33cd918 288 break;
marcel1691 1:2e29a33cd918 289 }
marcel1691 1:2e29a33cd918 290 }
marcel1691 1:2e29a33cd918 291
marcel1691 1:2e29a33cd918 292 if( trfLen == 0 ) {
marcel1691 1:2e29a33cd918 293 break;
marcel1691 1:2e29a33cd918 294 }
marcel1691 1:2e29a33cd918 295 }
marcel1691 1:2e29a33cd918 296
marcel1691 1:2e29a33cd918 297 }
marcel1691 1:2e29a33cd918 298
marcel1691 1:2e29a33cd918 299 //Receive response
marcel1691 1:2e29a33cd918 300 DBG("Receiving response");
marcel1691 1:2e29a33cd918 301 //ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
marcel1691 1:2e29a33cd918 302 ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); // recommended by Rob Noble to avoid timeout wait
marcel1691 1:2e29a33cd918 303 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 304 buf[trfLen] = '\0';
marcel1691 1:2e29a33cd918 305 INFO("Received \r\n(%s\r\n)", buf);
marcel1691 1:2e29a33cd918 306
marcel1691 1:2e29a33cd918 307 char* crlfPtr = strstr(buf, "\r\n");
marcel1691 1:2e29a33cd918 308 if( crlfPtr == NULL) {
marcel1691 1:2e29a33cd918 309 PRTCL_ERR();
marcel1691 1:2e29a33cd918 310 }
marcel1691 1:2e29a33cd918 311
marcel1691 1:2e29a33cd918 312 crlfPos = crlfPtr - buf;
marcel1691 1:2e29a33cd918 313 buf[crlfPos] = '\0';
marcel1691 1:2e29a33cd918 314
marcel1691 1:2e29a33cd918 315 //Parse HTTP response
marcel1691 1:2e29a33cd918 316 if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) {
marcel1691 1:2e29a33cd918 317 //Cannot match string, error
marcel1691 1:2e29a33cd918 318 ERR("Not a correct HTTP answer : {%s}\n", buf);
marcel1691 1:2e29a33cd918 319 PRTCL_ERR();
marcel1691 1:2e29a33cd918 320 }
marcel1691 1:2e29a33cd918 321
marcel1691 1:2e29a33cd918 322 if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 400) ) {
marcel1691 1:2e29a33cd918 323 //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers
marcel1691 1:2e29a33cd918 324 WARN("Response code %d", m_httpResponseCode);
marcel1691 1:2e29a33cd918 325 PRTCL_ERR();
marcel1691 1:2e29a33cd918 326 }
marcel1691 1:2e29a33cd918 327
marcel1691 1:2e29a33cd918 328 DBG("Reading headers");
marcel1691 1:2e29a33cd918 329
marcel1691 1:2e29a33cd918 330 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
marcel1691 1:2e29a33cd918 331 trfLen -= (crlfPos + 2);
marcel1691 1:2e29a33cd918 332
marcel1691 1:2e29a33cd918 333 recvContentLength = 0;
marcel1691 1:2e29a33cd918 334 recvChunked = false;
marcel1691 1:2e29a33cd918 335 //Now get headers
marcel1691 1:2e29a33cd918 336 while( true ) {
marcel1691 1:2e29a33cd918 337 crlfPtr = strstr(buf, "\r\n");
marcel1691 1:2e29a33cd918 338 if(crlfPtr == NULL) {
marcel1691 1:2e29a33cd918 339 if( trfLen < CHUNK_SIZE - 1 ) {
marcel1691 1:2e29a33cd918 340 size_t newTrfLen = 0;
marcel1691 1:2e29a33cd918 341 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
marcel1691 1:2e29a33cd918 342 trfLen += newTrfLen;
marcel1691 1:2e29a33cd918 343 buf[trfLen] = '\0';
marcel1691 1:2e29a33cd918 344 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
marcel1691 1:2e29a33cd918 345 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 346 continue;
marcel1691 1:2e29a33cd918 347 } else {
marcel1691 1:2e29a33cd918 348 PRTCL_ERR();
marcel1691 1:2e29a33cd918 349 }
marcel1691 1:2e29a33cd918 350 }
marcel1691 1:2e29a33cd918 351
marcel1691 1:2e29a33cd918 352 crlfPos = crlfPtr - buf;
marcel1691 1:2e29a33cd918 353
marcel1691 1:2e29a33cd918 354 if(crlfPos == 0) { //End of headers
marcel1691 1:2e29a33cd918 355 DBG("Headers read");
marcel1691 1:2e29a33cd918 356 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
marcel1691 1:2e29a33cd918 357 trfLen -= 2;
marcel1691 1:2e29a33cd918 358 break;
marcel1691 1:2e29a33cd918 359 }
marcel1691 1:2e29a33cd918 360
marcel1691 1:2e29a33cd918 361 buf[crlfPos] = '\0';
marcel1691 1:2e29a33cd918 362
marcel1691 1:2e29a33cd918 363 char key[32];
marcel1691 1:2e29a33cd918 364 char value[MAXLEN_VALUE];
marcel1691 1:2e29a33cd918 365
marcel1691 1:2e29a33cd918 366 key[31] = '\0';
marcel1691 1:2e29a33cd918 367 value[MAXLEN_VALUE - 1] = '\0';
marcel1691 1:2e29a33cd918 368
marcel1691 1:2e29a33cd918 369 int n = sscanf(buf, "%35[^:]: %156[^\r\n]", key, value);
marcel1691 1:2e29a33cd918 370 if ( n == 2 ) {
marcel1691 1:2e29a33cd918 371 DBG("Read header : %s: %s", key, value);
marcel1691 1:2e29a33cd918 372 if( !strcmp(key, "Content-Length") ) {
marcel1691 1:2e29a33cd918 373 sscanf(value, "%d", &recvContentLength);
marcel1691 1:2e29a33cd918 374 pDataIn->setDataLen(recvContentLength);
marcel1691 1:2e29a33cd918 375 } else if( !strcmp(key, "Transfer-Encoding") ) {
marcel1691 1:2e29a33cd918 376 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) {
marcel1691 1:2e29a33cd918 377 recvChunked = true;
marcel1691 1:2e29a33cd918 378 pDataIn->setIsChunked(true);
marcel1691 1:2e29a33cd918 379 }
marcel1691 1:2e29a33cd918 380 } else if( !strcmp(key, "Content-Type") ) {
marcel1691 1:2e29a33cd918 381 pDataIn->setDataType(value);
marcel1691 1:2e29a33cd918 382 } else if ( !strcmp(key, "Location") ) {
marcel1691 1:2e29a33cd918 383 if (m_location)
marcel1691 1:2e29a33cd918 384 free(m_location);
marcel1691 1:2e29a33cd918 385 m_location = (char *)malloc(strlen(value)+1);
marcel1691 1:2e29a33cd918 386 if (m_location) {
marcel1691 1:2e29a33cd918 387 strcpy(m_location,value);
marcel1691 1:2e29a33cd918 388 url = m_location;
marcel1691 1:2e29a33cd918 389 INFO("Following redirect[%d] to [%s]", maxRedirect, url);
marcel1691 1:2e29a33cd918 390 m_sock.close();
marcel1691 1:2e29a33cd918 391 takeRedirect = true;
marcel1691 1:2e29a33cd918 392 break; // exit the while(true) header to follow the redirect
marcel1691 1:2e29a33cd918 393 }
marcel1691 1:2e29a33cd918 394 }
marcel1691 1:2e29a33cd918 395
marcel1691 1:2e29a33cd918 396 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
marcel1691 1:2e29a33cd918 397 trfLen -= (crlfPos + 2);
marcel1691 1:2e29a33cd918 398 } else {
marcel1691 1:2e29a33cd918 399 ERR("Could not parse header");
marcel1691 1:2e29a33cd918 400 PRTCL_ERR();
marcel1691 1:2e29a33cd918 401 }
marcel1691 1:2e29a33cd918 402
marcel1691 1:2e29a33cd918 403 } // while(true) // get headers
marcel1691 1:2e29a33cd918 404 if (!takeRedirect)
marcel1691 1:2e29a33cd918 405 break;
marcel1691 1:2e29a33cd918 406 } // while (maxRedirect)
marcel1691 1:2e29a33cd918 407
marcel1691 1:2e29a33cd918 408 //Receive data
marcel1691 1:2e29a33cd918 409 DBG("Receiving data");
marcel1691 1:2e29a33cd918 410 while(true) {
marcel1691 1:2e29a33cd918 411 size_t readLen = 0;
marcel1691 1:2e29a33cd918 412
marcel1691 1:2e29a33cd918 413 if( recvChunked ) {
marcel1691 1:2e29a33cd918 414 //Read chunk header
marcel1691 1:2e29a33cd918 415 bool foundCrlf;
marcel1691 1:2e29a33cd918 416 do {
marcel1691 1:2e29a33cd918 417 foundCrlf = false;
marcel1691 1:2e29a33cd918 418 crlfPos=0;
marcel1691 1:2e29a33cd918 419 buf[trfLen]=0;
marcel1691 1:2e29a33cd918 420 if(trfLen >= 2) {
marcel1691 1:2e29a33cd918 421 for(; crlfPos < trfLen - 2; crlfPos++) {
marcel1691 1:2e29a33cd918 422 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) {
marcel1691 1:2e29a33cd918 423 foundCrlf = true;
marcel1691 1:2e29a33cd918 424 break;
marcel1691 1:2e29a33cd918 425 }
marcel1691 1:2e29a33cd918 426 }
marcel1691 1:2e29a33cd918 427 }
marcel1691 1:2e29a33cd918 428 if(!foundCrlf) { //Try to read more
marcel1691 1:2e29a33cd918 429 if( trfLen < CHUNK_SIZE ) {
marcel1691 1:2e29a33cd918 430 size_t newTrfLen = 0;
marcel1691 1:2e29a33cd918 431 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
marcel1691 1:2e29a33cd918 432 trfLen += newTrfLen;
marcel1691 1:2e29a33cd918 433 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 434 continue;
marcel1691 1:2e29a33cd918 435 } else {
marcel1691 1:2e29a33cd918 436 PRTCL_ERR();
marcel1691 1:2e29a33cd918 437 }
marcel1691 1:2e29a33cd918 438 }
marcel1691 1:2e29a33cd918 439 } while(!foundCrlf);
marcel1691 1:2e29a33cd918 440 buf[crlfPos] = '\0';
marcel1691 1:2e29a33cd918 441 int n = sscanf(buf, "%x", &readLen);
marcel1691 1:2e29a33cd918 442 if(n!=1) {
marcel1691 1:2e29a33cd918 443 ERR("Could not read chunk length");
marcel1691 1:2e29a33cd918 444 PRTCL_ERR();
marcel1691 1:2e29a33cd918 445 }
marcel1691 1:2e29a33cd918 446
marcel1691 1:2e29a33cd918 447 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
marcel1691 1:2e29a33cd918 448 trfLen -= (crlfPos + 2);
marcel1691 1:2e29a33cd918 449
marcel1691 1:2e29a33cd918 450 if( readLen == 0 ) {
marcel1691 1:2e29a33cd918 451 //Last chunk
marcel1691 1:2e29a33cd918 452 break;
marcel1691 1:2e29a33cd918 453 }
marcel1691 1:2e29a33cd918 454 } else {
marcel1691 1:2e29a33cd918 455 readLen = recvContentLength;
marcel1691 1:2e29a33cd918 456 }
marcel1691 1:2e29a33cd918 457
marcel1691 1:2e29a33cd918 458 DBG("Retrieving %d bytes", readLen);
marcel1691 1:2e29a33cd918 459
marcel1691 1:2e29a33cd918 460 do {
marcel1691 1:2e29a33cd918 461 INFO("write %d,%d: %s", trfLen, readLen, buf);
marcel1691 1:2e29a33cd918 462 pDataIn->write(buf, MIN(trfLen, readLen));
marcel1691 1:2e29a33cd918 463 if( trfLen > readLen ) {
marcel1691 1:2e29a33cd918 464 memmove(buf, &buf[readLen], trfLen - readLen);
marcel1691 1:2e29a33cd918 465 trfLen -= readLen;
marcel1691 1:2e29a33cd918 466 readLen = 0;
marcel1691 1:2e29a33cd918 467 } else {
marcel1691 1:2e29a33cd918 468 readLen -= trfLen;
marcel1691 1:2e29a33cd918 469 }
marcel1691 1:2e29a33cd918 470
marcel1691 1:2e29a33cd918 471 if(readLen) {
marcel1691 1:2e29a33cd918 472 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
marcel1691 1:2e29a33cd918 473 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 474 }
marcel1691 1:2e29a33cd918 475 } while(readLen);
marcel1691 1:2e29a33cd918 476
marcel1691 1:2e29a33cd918 477 if( recvChunked ) {
marcel1691 1:2e29a33cd918 478 if(trfLen < 2) {
marcel1691 1:2e29a33cd918 479 size_t newTrfLen;
marcel1691 1:2e29a33cd918 480 //Read missing chars to find end of chunk
marcel1691 1:2e29a33cd918 481 INFO("read chunk");
marcel1691 1:2e29a33cd918 482 ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen);
marcel1691 1:2e29a33cd918 483 CHECK_CONN_ERR(ret);
marcel1691 1:2e29a33cd918 484 trfLen += newTrfLen;
marcel1691 1:2e29a33cd918 485 }
marcel1691 1:2e29a33cd918 486 if( (buf[0] != '\r') || (buf[1] != '\n') ) {
marcel1691 1:2e29a33cd918 487 ERR("Format error");
marcel1691 1:2e29a33cd918 488 PRTCL_ERR();
marcel1691 1:2e29a33cd918 489 }
marcel1691 1:2e29a33cd918 490 memmove(buf, &buf[2], trfLen - 2);
marcel1691 1:2e29a33cd918 491 trfLen -= 2;
marcel1691 1:2e29a33cd918 492 } else {
marcel1691 1:2e29a33cd918 493 break;
marcel1691 1:2e29a33cd918 494 }
marcel1691 1:2e29a33cd918 495
marcel1691 1:2e29a33cd918 496 }
marcel1691 1:2e29a33cd918 497
marcel1691 1:2e29a33cd918 498 m_sock.close();
marcel1691 1:2e29a33cd918 499 DBG("Completed HTTP transaction");
marcel1691 1:2e29a33cd918 500
marcel1691 1:2e29a33cd918 501 return HTTP_OK;
marcel1691 1:2e29a33cd918 502 }
marcel1691 1:2e29a33cd918 503
marcel1691 1:2e29a33cd918 504 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure
marcel1691 1:2e29a33cd918 505 {
marcel1691 1:2e29a33cd918 506 DBG("Trying to read between %d and %d bytes", minLen, maxLen);
marcel1691 1:2e29a33cd918 507 size_t readLen = 0;
marcel1691 1:2e29a33cd918 508
marcel1691 1:2e29a33cd918 509 if (!m_sock.is_connected()) {
marcel1691 1:2e29a33cd918 510 WARN("Connection was closed by server");
marcel1691 1:2e29a33cd918 511 return HTTP_CLOSED; //Connection was closed by server
marcel1691 1:2e29a33cd918 512 }
marcel1691 1:2e29a33cd918 513
marcel1691 1:2e29a33cd918 514 int ret;
marcel1691 1:2e29a33cd918 515 while (readLen < maxLen) {
marcel1691 1:2e29a33cd918 516 if (readLen < minLen) {
marcel1691 1:2e29a33cd918 517 DBG("Trying to read at most %4d bytes [Blocking] %d,%d", minLen - readLen, minLen, readLen);
marcel1691 1:2e29a33cd918 518 m_sock.set_blocking(false, m_timeout);
marcel1691 1:2e29a33cd918 519 ret = m_sock.receive_all(buf + readLen, minLen - readLen);
marcel1691 1:2e29a33cd918 520 } else {
marcel1691 1:2e29a33cd918 521 DBG("Trying to read at most %4d bytes [Not blocking] %d,%d", maxLen - readLen, maxLen, readLen);
marcel1691 1:2e29a33cd918 522 m_sock.set_blocking(false, 0);
marcel1691 1:2e29a33cd918 523 ret = m_sock.receive(buf + readLen, maxLen - readLen);
marcel1691 1:2e29a33cd918 524 }
marcel1691 1:2e29a33cd918 525
marcel1691 1:2e29a33cd918 526 if (ret > 0) {
marcel1691 1:2e29a33cd918 527 readLen += ret;
marcel1691 1:2e29a33cd918 528 } else if ( ret == 0 ) {
marcel1691 1:2e29a33cd918 529 break;
marcel1691 1:2e29a33cd918 530 } else {
marcel1691 1:2e29a33cd918 531 if (!m_sock.is_connected()) {
marcel1691 1:2e29a33cd918 532 ERR("Connection error (recv returned %d)", ret);
marcel1691 1:2e29a33cd918 533 *pReadLen = readLen;
marcel1691 1:2e29a33cd918 534 return HTTP_CONN;
marcel1691 1:2e29a33cd918 535 } else {
marcel1691 1:2e29a33cd918 536 break;
marcel1691 1:2e29a33cd918 537 }
marcel1691 1:2e29a33cd918 538 }
marcel1691 1:2e29a33cd918 539 if (!m_sock.is_connected()) {
marcel1691 1:2e29a33cd918 540 break;
marcel1691 1:2e29a33cd918 541 }
marcel1691 1:2e29a33cd918 542 }
marcel1691 1:2e29a33cd918 543 DBG("Read %d bytes", readLen);
marcel1691 1:2e29a33cd918 544 buf[readLen] = '\0'; // DS makes it easier to see what's new.
marcel1691 1:2e29a33cd918 545 *pReadLen = readLen;
marcel1691 1:2e29a33cd918 546 return HTTP_OK;
marcel1691 1:2e29a33cd918 547 }
marcel1691 1:2e29a33cd918 548
marcel1691 1:2e29a33cd918 549 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure
marcel1691 1:2e29a33cd918 550 {
marcel1691 1:2e29a33cd918 551 if(len == 0) {
marcel1691 1:2e29a33cd918 552 len = strlen(buf);
marcel1691 1:2e29a33cd918 553 }
marcel1691 1:2e29a33cd918 554 DBG("send(%s,%d)", buf, len);
marcel1691 1:2e29a33cd918 555 size_t writtenLen = 0;
marcel1691 1:2e29a33cd918 556
marcel1691 1:2e29a33cd918 557 if(!m_sock.is_connected()) {
marcel1691 1:2e29a33cd918 558 WARN("Connection was closed by server");
marcel1691 1:2e29a33cd918 559 return HTTP_CLOSED; //Connection was closed by server
marcel1691 1:2e29a33cd918 560 }
marcel1691 1:2e29a33cd918 561
marcel1691 1:2e29a33cd918 562 m_sock.set_blocking(false, m_timeout);
marcel1691 1:2e29a33cd918 563 int ret = m_sock.send_all(buf, len);
marcel1691 1:2e29a33cd918 564 if(ret > 0) {
marcel1691 1:2e29a33cd918 565 writtenLen += ret;
marcel1691 1:2e29a33cd918 566 } else if( ret == 0 ) {
marcel1691 1:2e29a33cd918 567 WARN("Connection was closed by server");
marcel1691 1:2e29a33cd918 568 return HTTP_CLOSED; //Connection was closed by server
marcel1691 1:2e29a33cd918 569 } else {
marcel1691 1:2e29a33cd918 570 ERR("Connection error (send returned %d)", ret);
marcel1691 1:2e29a33cd918 571 return HTTP_CONN;
marcel1691 1:2e29a33cd918 572 }
marcel1691 1:2e29a33cd918 573
marcel1691 1:2e29a33cd918 574 DBG("Written %d bytes", writtenLen);
marcel1691 1:2e29a33cd918 575 return HTTP_OK;
marcel1691 1:2e29a33cd918 576 }
marcel1691 1:2e29a33cd918 577
marcel1691 1:2e29a33cd918 578 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
marcel1691 1:2e29a33cd918 579 {
marcel1691 1:2e29a33cd918 580 char* schemePtr = (char*) url;
marcel1691 1:2e29a33cd918 581 char* hostPtr = (char*) strstr(url, "://");
marcel1691 1:2e29a33cd918 582 if(hostPtr == NULL) {
marcel1691 1:2e29a33cd918 583 WARN("Could not find host");
marcel1691 1:2e29a33cd918 584 return HTTP_PARSE; //URL is invalid
marcel1691 1:2e29a33cd918 585 }
marcel1691 1:2e29a33cd918 586
marcel1691 1:2e29a33cd918 587 if( maxSchemeLen < hostPtr - schemePtr + 1 ) { //including NULL-terminating char
marcel1691 1:2e29a33cd918 588 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
marcel1691 1:2e29a33cd918 589 return HTTP_PARSE;
marcel1691 1:2e29a33cd918 590 }
marcel1691 1:2e29a33cd918 591 memcpy(scheme, schemePtr, hostPtr - schemePtr);
marcel1691 1:2e29a33cd918 592 scheme[hostPtr - schemePtr] = '\0';
marcel1691 1:2e29a33cd918 593
marcel1691 1:2e29a33cd918 594 hostPtr+=3;
marcel1691 1:2e29a33cd918 595
marcel1691 1:2e29a33cd918 596 size_t hostLen = 0;
marcel1691 1:2e29a33cd918 597
marcel1691 1:2e29a33cd918 598 char* portPtr = strchr(hostPtr, ':');
marcel1691 1:2e29a33cd918 599 if( portPtr != NULL ) {
marcel1691 1:2e29a33cd918 600 hostLen = portPtr - hostPtr;
marcel1691 1:2e29a33cd918 601 portPtr++;
marcel1691 1:2e29a33cd918 602 if( sscanf(portPtr, "%hu", port) != 1) {
marcel1691 1:2e29a33cd918 603 WARN("Could not find port");
marcel1691 1:2e29a33cd918 604 return HTTP_PARSE;
marcel1691 1:2e29a33cd918 605 }
marcel1691 1:2e29a33cd918 606 } else {
marcel1691 1:2e29a33cd918 607 *port=0;
marcel1691 1:2e29a33cd918 608 }
marcel1691 1:2e29a33cd918 609 char* pathPtr = strchr(hostPtr, '/');
marcel1691 1:2e29a33cd918 610 if( hostLen == 0 ) {
marcel1691 1:2e29a33cd918 611 hostLen = pathPtr - hostPtr;
marcel1691 1:2e29a33cd918 612 }
marcel1691 1:2e29a33cd918 613
marcel1691 1:2e29a33cd918 614 if( maxHostLen < hostLen + 1 ) { //including NULL-terminating char
marcel1691 1:2e29a33cd918 615 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
marcel1691 1:2e29a33cd918 616 return HTTP_PARSE;
marcel1691 1:2e29a33cd918 617 }
marcel1691 1:2e29a33cd918 618 memcpy(host, hostPtr, hostLen);
marcel1691 1:2e29a33cd918 619 host[hostLen] = '\0';
marcel1691 1:2e29a33cd918 620
marcel1691 1:2e29a33cd918 621 size_t pathLen;
marcel1691 1:2e29a33cd918 622 char* fragmentPtr = strchr(hostPtr, '#');
marcel1691 1:2e29a33cd918 623 if(fragmentPtr != NULL) {
marcel1691 1:2e29a33cd918 624 pathLen = fragmentPtr - pathPtr;
marcel1691 1:2e29a33cd918 625 } else {
marcel1691 1:2e29a33cd918 626 pathLen = strlen(pathPtr);
marcel1691 1:2e29a33cd918 627 }
marcel1691 1:2e29a33cd918 628
marcel1691 1:2e29a33cd918 629 if( maxPathLen < pathLen + 1 ) { //including NULL-terminating char
marcel1691 1:2e29a33cd918 630 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
marcel1691 1:2e29a33cd918 631 return HTTP_PARSE;
marcel1691 1:2e29a33cd918 632 }
marcel1691 1:2e29a33cd918 633 memcpy(path, pathPtr, pathLen);
marcel1691 1:2e29a33cd918 634 path[pathLen] = '\0';
marcel1691 1:2e29a33cd918 635
marcel1691 1:2e29a33cd918 636 return HTTP_OK;
marcel1691 1:2e29a33cd918 637 }
marcel1691 1:2e29a33cd918 638
marcel1691 1:2e29a33cd918 639 void HTTPClient::createauth (const char *user, const char *pwd, char *buf, int len)
marcel1691 1:2e29a33cd918 640 {
marcel1691 1:2e29a33cd918 641 char tmp[80];
marcel1691 1:2e29a33cd918 642
marcel1691 1:2e29a33cd918 643 snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
marcel1691 1:2e29a33cd918 644 base64enc(tmp, strlen(tmp), &buf[strlen(buf)], len - strlen(buf));
marcel1691 1:2e29a33cd918 645 }
marcel1691 1:2e29a33cd918 646
marcel1691 1:2e29a33cd918 647 // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
marcel1691 1:2e29a33cd918 648 int HTTPClient::base64enc(const char *input, unsigned int length, char *output, int len)
marcel1691 1:2e29a33cd918 649 {
marcel1691 1:2e29a33cd918 650 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
marcel1691 1:2e29a33cd918 651 unsigned int c, c1, c2, c3;
marcel1691 1:2e29a33cd918 652
marcel1691 1:2e29a33cd918 653 if (len < ((((length-1)/3)+1)<<2)) return -1;
marcel1691 1:2e29a33cd918 654 for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
marcel1691 1:2e29a33cd918 655 c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
marcel1691 1:2e29a33cd918 656 c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
marcel1691 1:2e29a33cd918 657 c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
marcel1691 1:2e29a33cd918 658
marcel1691 1:2e29a33cd918 659 c = ((c1 & 0xFC) >> 2);
marcel1691 1:2e29a33cd918 660 output[j+0] = base64[c];
marcel1691 1:2e29a33cd918 661 c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
marcel1691 1:2e29a33cd918 662 output[j+1] = base64[c];
marcel1691 1:2e29a33cd918 663 c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
marcel1691 1:2e29a33cd918 664 output[j+2] = (length>i+1)?base64[c]:'=';
marcel1691 1:2e29a33cd918 665 c = (c3 & 0x3F);
marcel1691 1:2e29a33cd918 666 output[j+3] = (length>i+2)?base64[c]:'=';
marcel1691 1:2e29a33cd918 667 }
marcel1691 1:2e29a33cd918 668 output[(((length-1)/3)+1)<<2] = '\0';
marcel1691 1:2e29a33cd918 669 return 0;
marcel1691 1:2e29a33cd918 670 }