Integrating the ublox LISA C200 modem

Fork of SprintUSBModemHTTPClientTest by Donatien Garnier

Committer:
sam_grove
Date:
Tue Oct 08 00:08:22 2013 +0000
Revision:
21:3f45e53afe4f
Parent:
5:3f93dd1d4cb3
Added http client test. Return from post seems to be a bit wonky but haven't looked closely at this

Who changed what in which revision?

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