Fork HTTPClient and Modfiy code for mbed 6.0

Dependents:   mbed-demo-http-get-json

Committer:
quxiaorui
Date:
Sun Nov 08 10:33:36 2020 +0000
Revision:
51:a9ed5a6eee90
Parent:
50:1c1409029b05
remove unnecessary annotation.

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