PullRequest

Dependents:   CyaSSL-Twitter-OAuth4Tw TweetTest NetworkThermometer CyaSSL-Twitter-OAuth4Tw_arrange

Fork of HTTPClient by wolf SSL

Revision:
18:d89df40b4cf3
Parent:
17:c73d8e61d391
Child:
19:1e2f05809eb1
--- a/HTTPClient.cpp	Mon Apr 07 23:30:35 2014 +0000
+++ b/HTTPClient.cpp	Mon Apr 07 23:41:06 2014 +0000
@@ -21,15 +21,15 @@
 #if 0
 //Enable debug
 #include <cstdio>
-#define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 
-#define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 
-#define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 
+#define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__);
+#define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__);
+#define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__);
 
 #else
 //Disable debug
-#define DBG(x, ...) 
+#define DBG(x, ...)
 #define WARN(x, ...)
-#define ERR(x, ...) 
+#define ERR(x, ...)
 
 #endif
 
@@ -51,7 +51,7 @@
 #include "HTTPClient.h"
 #include "TCPSocketConnection.h"
 
-class TCPSocketConnection_fd: public TCPSocketConnection 
+class TCPSocketConnection_fd: public TCPSocketConnection
 {
 public:
     int get_fd() {
@@ -70,7 +70,7 @@
 {
     int n ;
     int i ;
-    #define RECV_RETRY 3
+#define RECV_RETRY 3
     for(i=0; i<RECV_RETRY; i++) {
         n = m_sock.receive(buf, sz) ;
         if(n >= 0)return n  ;
@@ -91,11 +91,11 @@
 }
 
 HTTPClient::HTTPClient() :
-m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
+    m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
 {
-  //CyaSSL_Debugging_ON() ;
-  ctx = 0 ;
-  ssl = 0 ;
+    //CyaSSL_Debugging_ON() ;
+    ctx = 0 ;
+    ssl = 0 ;
 }
 
 HTTPClient::~HTTPClient()
@@ -106,41 +106,41 @@
 #if 0
 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
 {
-  m_basicAuthUser = user;
-  m_basicAuthPassword = password;
+    m_basicAuthUser = user;
+    m_basicAuthPassword = password;
 }
 #endif
 
 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
 {
-  return connect(url, HTTP_GET, NULL, pDataIn, timeout);
+    return connect(url, HTTP_GET, NULL, pDataIn, timeout);
 }
 
 HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
 {
-  HTTPText str(result, maxResultLen);
-  return get(url, &str, timeout);
+    HTTPText str(result, maxResultLen);
+    return get(url, &str, timeout);
 }
 
 HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
 {
-  return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
+    return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
 }
 
 HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
 {
-  return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
+    return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
 }
 
 HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
 {
-  return connect(url, HTTP_DELETE, NULL, pDataIn, timeout);
+    return connect(url, HTTP_DELETE, NULL, pDataIn, timeout);
 }
 
 
 int HTTPClient::getHTTPResponseCode()
 {
-  return m_httpResponseCode;
+    return m_httpResponseCode;
 }
 
 void HTTPClient::setHeader(char * h)
@@ -177,654 +177,558 @@
 
 
 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request
-{ 
-  m_httpResponseCode = 0; //Invalidate code
-  m_timeout = timeout;
-  
-  pDataIn->writeReset();
-  if( pDataOut )
-  {
-    pDataOut->readReset();
-  }
+{
+    m_httpResponseCode = 0; //Invalidate code
+    m_timeout = timeout;
 
-  char scheme[8];
-  char host[32];
-  char path[64];
-
-  int ret ;
+    pDataIn->writeReset();
+    if( pDataOut ) {
+        pDataOut->readReset();
+    }
 
-  //First we need to parse the url (http[s]://host[:port][/[path]]) 
-  HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
-  if(res != HTTP_OK)
-  {
-    ERR("parseURL returned %d", res);
-    return res;
-  }
+    char scheme[8];
+    char host[32];
+    char path[64];
+
+    int ret ;
 
-  if(port == 0) //TODO do handle HTTPS->443
-  {
-    if(strcmp(scheme, "http") == 0)
-      port = HTTP_PORT ;
-    else if(strcmp(scheme, "https") == 0)
-      port = HTTPS_PORT ;
-  }
+    //First we need to parse the url (http[s]://host[:port][/[path]])
+    HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
+    if(res != HTTP_OK) {
+        ERR("parseURL returned %d", res);
+        return res;
+    }
 
-  DBG("Scheme: %s", scheme);
-  DBG("Host: %s", host);
-  DBG("Port: %d", port);
-  DBG("Path: %s", path);
+    if(port == 0) { //TODO do handle HTTPS->443
+        if(strcmp(scheme, "http") == 0)
+            port = HTTP_PORT ;
+        else if(strcmp(scheme, "https") == 0)
+            port = HTTPS_PORT ;
+    }
 
-  //Connect
-  DBG("Connecting socket to server");
-  sockfd = m_sock.get_fd() ;
-  
-  #define MAX_RETRY 5
-  int retry ;
+    DBG("Scheme: %s", scheme);
+    DBG("Host: %s", host);
+    DBG("Port: %d", port);
+    DBG("Path: %s", path);
 
-  for(retry=0; retry<MAX_RETRY; retry++) {
-    int ret = m_sock.connect(host, port);
-    if(ret == 0)break ;
-  }
-  if(retry == MAX_RETRY)
-  {
-    m_sock.close();
-    ERR("Could not connect");
-    return HTTP_CONN;
-  }
+    //Connect
+    DBG("Connecting socket to server");
+    sockfd = m_sock.get_fd() ;
+
+#define MAX_RETRY 5
+    int retry ;
 
-  if(port == HTTPS_PORT) { 
-  /* Start SSL connect */
-    ctx = CyaSSL_CTX_new(
-    CyaTLSv1_2_client_method
-                      //CyaSSLv3_client_method
-    ());
-    if (ctx == NULL) {
-      ERR("unable to get ctx");
-      return HTTP_CONN;
+    for(retry=0; retry<MAX_RETRY; retry++) {
+        int ret = m_sock.connect(host, port);
+        if(ret == 0)break ;
     }
-    CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
-
-    ssl = CyaSSL_new(ctx);
-    if (ssl == NULL) {
-       ERR("unable to get SSL object");
-       cyassl_free() ;
-       return HTTP_CONN;
+    if(retry == MAX_RETRY) {
+        m_sock.close();
+        ERR("Could not connect");
+        return HTTP_CONN;
     }
 
-    CyaSSL_SetVersion(ssl, CYASSL_TLSV1_2) ;
-    CyaSSL_set_fd(ssl, sockfd);
-    CyaSSL_SetIORecv(ctx, SocketReceive) ;
-    CyaSSL_SetIOSend(ctx, SocketSend) ;
-    DBG("ctx=%x, ssl=%x, ssl->ctx->CBIORecv, CBIOSend=%x, %x\n",
-    ctx, ssl, SocketReceive, SocketSend ) ;
-    if (CyaSSL_connect(ssl) != SSL_SUCCESS) {
-      ERR("SSL_connect failed");
-      cyassl_free() ;
-      return HTTP_CONN;
-    }
-  } /* SSL connect complete */
-  
-  //Send request
-  DBG("Sending request");
-  char buf[CHUNK_SIZE];
-  send_buf_p = send_buf ; // Reset send buffer ;
-  
-  const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":"";
-  snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request
-  ret = send(buf);
-  if(ret)
-  {
-    m_sock.close();
-    ERR("Could not write request");
-    return HTTP_CONN;
-  }
+    if(port == HTTPS_PORT) {
+        /* Start SSL connect */
+        ctx = CyaSSL_CTX_new(
+                  CyaTLSv1_2_client_method
+                  //CyaSSLv3_client_method
+                  ());
+        if (ctx == NULL) {
+            ERR("unable to get ctx");
+            return HTTP_CONN;
+        }
+        CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
+
+        ssl = CyaSSL_new(ctx);
+        if (ssl == NULL) {
+            ERR("unable to get SSL object");
+            cyassl_free() ;
+            return HTTP_CONN;
+        }
 
-  //Send all headers
+        CyaSSL_SetVersion(ssl, CYASSL_TLSV1_2) ;
+        CyaSSL_set_fd(ssl, sockfd);
+        CyaSSL_SetIORecv(ctx, SocketReceive) ;
+        CyaSSL_SetIOSend(ctx, SocketSend) ;
+        DBG("ctx=%x, ssl=%x, ssl->ctx->CBIORecv, CBIOSend=%x, %x\n",
+            ctx, ssl, SocketReceive, SocketSend ) ;
+        if (CyaSSL_connect(ssl) != SSL_SUCCESS) {
+            ERR("SSL_connect failed");
+            cyassl_free() ;
+            return HTTP_CONN;
+        }
+    } /* SSL connect complete */
 
-  //Send default headers
-  DBG("Sending headers");
-  if( pDataOut != NULL )
-  {
-    if( pDataOut->getIsChunked() )
-    {
-      ret = send("Transfer-Encoding: chunked\r\n");
-      CHECK_CONN_ERR(ret);
-    }
-    else
-    {
-      snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen());
-      ret = send(buf);
-      CHECK_CONN_ERR(ret);
-    }
-    char type[48];
-    if( pDataOut->getDataType(type, 48) == HTTP_OK )
-    {
-      snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type);
-      ret = send(buf);
-      CHECK_CONN_ERR(ret);
+    //Send request
+    DBG("Sending request");
+    char buf[CHUNK_SIZE];
+    send_buf_p = send_buf ; // Reset send buffer ;
+
+    const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":"";
+    snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request
+    ret = send(buf);
+    if(ret) {
+        m_sock.close();
+        ERR("Could not write request");
+        return HTTP_CONN;
     }
-  }
-  
-  //Add user headers
-  if(header) {
-    ret = send(header);
-    CHECK_CONN_ERR(ret);
-  }
 
-  //Close headers
-  DBG("Headers sent");
-  ret = send("\r\n");
-  CHECK_CONN_ERR(ret);
+    //Send all headers
 
-  size_t trfLen;
-  
-  //Send data (if available)
-  if( pDataOut != NULL )
-  {
-    DBG("Sending data");
-    while(true)
-    {
-      size_t writtenLen = 0;
-      pDataOut->read(buf, CHUNK_SIZE, &trfLen);
-      buf[trfLen] = 0x0 ;
-      DBG("buf:%s", buf) ;
-      if( pDataOut->getIsChunked() )
-      {
-        //Write chunk header
-        char chunkHeader[16];
-        snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
-        ret = send(chunkHeader);
+    //Send default headers
+    DBG("Sending headers");
+    if( pDataOut != NULL ) {
+        if( pDataOut->getIsChunked() ) {
+            ret = send("Transfer-Encoding: chunked\r\n");
+            CHECK_CONN_ERR(ret);
+        } else {
+            snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen());
+            ret = send(buf);
+            CHECK_CONN_ERR(ret);
+        }
+        char type[48];
+        if( pDataOut->getDataType(type, 48) == HTTP_OK ) {
+            snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type);
+            ret = send(buf);
+            CHECK_CONN_ERR(ret);
+        }
+    }
+
+    //Add user headers
+    if(header) {
+        ret = send(header);
         CHECK_CONN_ERR(ret);
-      }
-      else if( trfLen == 0 )
-      {
-        break;
-      }
-      if( trfLen != 0 )
-      {
-        ret = send(buf, trfLen);
-        CHECK_CONN_ERR(ret);
-      }
-
-      if( pDataOut->getIsChunked()  )
-      {
-        ret = send("\r\n"); //Chunk-terminating CRLF
-        CHECK_CONN_ERR(ret);
-      }
-      else
-      {
-        writtenLen += trfLen;
-        if( writtenLen >= pDataOut->getDataLen() )
-        {
-          break;
-        }
-      }
-
-      if( trfLen == 0 )
-      {
-        break;
-      }
     }
 
-  }
-  ret = flush() ; // flush the send buffer ;
-  CHECK_CONN_ERR(ret);
-  
-  //Receive response
-  DBG("Receiving response");
+    //Close headers
+    DBG("Headers sent");
+    ret = send("\r\n");
+    CHECK_CONN_ERR(ret);
 
-  ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
-  CHECK_CONN_ERR(ret);
-
-  buf[trfLen] = '\0';
+    size_t trfLen;
 
-  char* crlfPtr = strstr(buf, "\r\n");
-  if(crlfPtr == NULL)
-  {
-    PRTCL_ERR();
-  }
-
-  int crlfPos = crlfPtr - buf;
-  buf[crlfPos] = '\0';
-
-  //Parse HTTP response
-  if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 )
-  {
-    //Cannot match string, error
-    ERR("Not a correct HTTP answer : %s\n", buf);
-    PRTCL_ERR();
-  }
+    //Send data (if available)
+    if( pDataOut != NULL ) {
+        DBG("Sending data");
+        while(true) {
+            size_t writtenLen = 0;
+            pDataOut->read(buf, CHUNK_SIZE, &trfLen);
+            buf[trfLen] = 0x0 ;
+            DBG("buf:%s", buf) ;
+            if( pDataOut->getIsChunked() ) {
+                //Write chunk header
+                char chunkHeader[16];
+                snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
+                ret = send(chunkHeader);
+                CHECK_CONN_ERR(ret);
+            } else if( trfLen == 0 ) {
+                break;
+            }
+            if( trfLen != 0 ) {
+                ret = send(buf, trfLen);
+                CHECK_CONN_ERR(ret);
+            }
 
-  if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) )
-  {
-    //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers 
-    WARN("Response code %d", m_httpResponseCode);
-    PRTCL_ERR();
-  }
+            if( pDataOut->getIsChunked()  ) {
+                ret = send("\r\n"); //Chunk-terminating CRLF
+                CHECK_CONN_ERR(ret);
+            } else {
+                writtenLen += trfLen;
+                if( writtenLen >= pDataOut->getDataLen() ) {
+                    break;
+                }
+            }
 
-  DBG("Reading headers");
-
-  memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
-  trfLen -= (crlfPos + 2);
+            if( trfLen == 0 ) {
+                break;
+            }
+        }
 
-  size_t recvContentLength = 0;
-  bool recvChunked = false;
-  //Now get headers
-  while( true )
-  {
-    crlfPtr = strstr(buf, "\r\n");
-    if(crlfPtr == NULL)
-    {
-      if( trfLen < CHUNK_SIZE - 1 )
-      {
-        size_t newTrfLen;
-        ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
-        trfLen += newTrfLen;
-        buf[trfLen] = '\0';
-        DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
-        CHECK_CONN_ERR(ret);
-        continue;
-      }
-      else
-      {
+    }
+    ret = flush() ; // flush the send buffer ;
+    CHECK_CONN_ERR(ret);
+
+    //Receive response
+    DBG("Receiving response");
+
+    ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
+    CHECK_CONN_ERR(ret);
+
+    buf[trfLen] = '\0';
+
+    char* crlfPtr = strstr(buf, "\r\n");
+    if(crlfPtr == NULL) {
         PRTCL_ERR();
-      }
     }
 
-    crlfPos = crlfPtr - buf;
-
-    if(crlfPos == 0) //End of headers
-    {
-      DBG("Headers read");
-      memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
-      trfLen -= 2;
-      break;
-    }
-
+    int crlfPos = crlfPtr - buf;
     buf[crlfPos] = '\0';
 
-    char key[32];
-    char value[32];
-
-    key[31] = '\0';
-    value[31] = '\0';
+    //Parse HTTP response
+    if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) {
+        //Cannot match string, error
+        ERR("Not a correct HTTP answer : %s\n", buf);
+        PRTCL_ERR();
+    }
 
-    int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
-    if ( n == 2 )
-    {
-      DBG("Read header : %s: %s\n", key, value);
-      if( !strcmp(key, "Content-Length") )
-      {
-        sscanf(value, "%d", &recvContentLength);
-        pDataIn->setDataLen(recvContentLength);
-      }
-      else if( !strcmp(key, "Transfer-Encoding") )
-      {
-        if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") )
-        {
-          recvChunked = true;
-          pDataIn->setIsChunked(true);
-        }
-      }
-      else if( !strcmp(key, "Content-Type") )
-      {
-        pDataIn->setDataType(value);
-      }
-
-      memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
-      trfLen -= (crlfPos + 2);
-
-    }
-    else
-    {
-      ERR("Could not parse header");
-      PRTCL_ERR();
+    if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) ) {
+        //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers
+        WARN("Response code %d", m_httpResponseCode);
+        PRTCL_ERR();
     }
 
-  }
+    DBG("Reading headers");
 
-  //Receive data
-  DBG("Receiving data");
-
-  while(true)
-  {
-    size_t readLen = 0;
+    memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
+    trfLen -= (crlfPos + 2);
 
-    if( recvChunked )
-    {
-      //Read chunk header
-      bool foundCrlf;
-      do
-      {
-        foundCrlf = false;
-        crlfPos=0;
-        buf[trfLen]=0;
-        if(trfLen >= 2)
-        {
-          for(; crlfPos < trfLen - 2; crlfPos++)
-          {
-            if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' )
-            {
-              foundCrlf = true;
-              break;
+    size_t recvContentLength = 0;
+    bool recvChunked = false;
+    //Now get headers
+    while( true ) {
+        crlfPtr = strstr(buf, "\r\n");
+        if(crlfPtr == NULL) {
+            if( trfLen < CHUNK_SIZE - 1 ) {
+                size_t newTrfLen;
+                ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
+                trfLen += newTrfLen;
+                buf[trfLen] = '\0';
+                DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
+                CHECK_CONN_ERR(ret);
+                continue;
+            } else {
+                PRTCL_ERR();
             }
-          }
+        }
+
+        crlfPos = crlfPtr - buf;
+
+        if(crlfPos == 0) { //End of headers
+            DBG("Headers read");
+            memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
+            trfLen -= 2;
+            break;
         }
-        if(!foundCrlf) //Try to read more
-        {
-          if( trfLen < CHUNK_SIZE )
-          {
-            size_t newTrfLen;
-            ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
-            trfLen += newTrfLen;
-            CHECK_CONN_ERR(ret);
-            continue;
-          }
-          else
-          {
+
+        buf[crlfPos] = '\0';
+
+        char key[32];
+        char value[32];
+
+        key[31] = '\0';
+        value[31] = '\0';
+
+        int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
+        if ( n == 2 ) {
+            DBG("Read header : %s: %s\n", key, value);
+            if( !strcmp(key, "Content-Length") ) {
+                sscanf(value, "%d", &recvContentLength);
+                pDataIn->setDataLen(recvContentLength);
+            } else if( !strcmp(key, "Transfer-Encoding") ) {
+                if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) {
+                    recvChunked = true;
+                    pDataIn->setIsChunked(true);
+                }
+            } else if( !strcmp(key, "Content-Type") ) {
+                pDataIn->setDataType(value);
+            }
+
+            memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
+            trfLen -= (crlfPos + 2);
+
+        } else {
+            ERR("Could not parse header");
             PRTCL_ERR();
-          }
         }
-      } while(!foundCrlf);
-      buf[crlfPos] = '\0';
-      int n = sscanf(buf, "%x", &readLen);
-      if(n!=1)
-      {
-        ERR("Could not read chunk length");
-        PRTCL_ERR();
-      }
 
-      memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
-      trfLen -= (crlfPos + 2);
-
-      if( readLen == 0 )
-      {
-        //Last chunk
-        break;
-      }
-    }
-    else
-    {
-      readLen = recvContentLength;
     }
 
-    DBG("Retrieving %d bytes", readLen);
+    //Receive data
+    DBG("Receiving data");
+
+    while(true) {
+        size_t readLen = 0;
 
-    do
-    {
-      pDataIn->write(buf, MIN(trfLen, readLen));
-      if( trfLen > readLen )
-      {
-        memmove(buf, &buf[readLen], trfLen - readLen);
-        trfLen -= readLen;
-        readLen = 0;
-      }
-      else
-      {
-        readLen -= trfLen;
-      }
+        if( recvChunked ) {
+            //Read chunk header
+            bool foundCrlf;
+            do {
+                foundCrlf = false;
+                crlfPos=0;
+                buf[trfLen]=0;
+                if(trfLen >= 2) {
+                    for(; crlfPos < trfLen - 2; crlfPos++) {
+                        if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) {
+                            foundCrlf = true;
+                            break;
+                        }
+                    }
+                }
+                if(!foundCrlf) { //Try to read more
+                    if( trfLen < CHUNK_SIZE ) {
+                        size_t newTrfLen;
+                        ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
+                        trfLen += newTrfLen;
+                        CHECK_CONN_ERR(ret);
+                        continue;
+                    } else {
+                        PRTCL_ERR();
+                    }
+                }
+            } while(!foundCrlf);
+            buf[crlfPos] = '\0';
+            int n = sscanf(buf, "%x", &readLen);
+            if(n!=1) {
+                ERR("Could not read chunk length");
+                PRTCL_ERR();
+            }
+
+            memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
+            trfLen -= (crlfPos + 2);
 
-      if(readLen)
-      {
-        ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
-        CHECK_CONN_ERR(ret);
-      }
-    } while(readLen);
+            if( readLen == 0 ) {
+                //Last chunk
+                break;
+            }
+        } else {
+            readLen = recvContentLength;
+        }
+
+        DBG("Retrieving %d bytes", readLen);
+
+        do {
+            pDataIn->write(buf, MIN(trfLen, readLen));
+            if( trfLen > readLen ) {
+                memmove(buf, &buf[readLen], trfLen - readLen);
+                trfLen -= readLen;
+                readLen = 0;
+            } else {
+                readLen -= trfLen;
+            }
 
-    if( recvChunked )
-    {
-      if(trfLen < 2)
-      {
-        size_t newTrfLen;
-        //Read missing chars to find end of chunk
-        ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen);
-        CHECK_CONN_ERR(ret);
-        trfLen += newTrfLen;
-      }
-      if( (buf[0] != '\r') || (buf[1] != '\n') )
-      {
-        ERR("Format error");
-        PRTCL_ERR();
-      }
-      memmove(buf, &buf[2], trfLen - 2);
-      trfLen -= 2;
-    }
-    else
-    {
-      break;
+            if(readLen) {
+                ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
+                CHECK_CONN_ERR(ret);
+            }
+        } while(readLen);
+
+        if( recvChunked ) {
+            if(trfLen < 2) {
+                size_t newTrfLen;
+                //Read missing chars to find end of chunk
+                ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen);
+                CHECK_CONN_ERR(ret);
+                trfLen += newTrfLen;
+            }
+            if( (buf[0] != '\r') || (buf[1] != '\n') ) {
+                ERR("Format error");
+                PRTCL_ERR();
+            }
+            memmove(buf, &buf[2], trfLen - 2);
+            trfLen -= 2;
+        } else {
+            break;
+        }
+
     }
 
-  }
-  
-  cyassl_free() ;
-  m_sock.close();
-  DBG("Completed HTTP transaction");
+    cyassl_free() ;
+    m_sock.close();
+    DBG("Completed HTTP transaction");
 
-  return HTTP_OK;
+    return HTTP_OK;
 }
 
 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure
 {
-  DBG("Trying to read between %d and %d bytes", minLen, maxLen);
-  size_t readLen = 0;
-      
-  if(!m_sock.is_connected())
-  {
-    WARN("Connection was closed by server");
-    return HTTP_CLOSED; //Connection was closed by server 
-  }
-    
-  int ret;
-  
-  if(port == HTTPS_PORT) {
-    DBG("Enter CyaSSL_read") ;
-    
-    m_sock.set_blocking(false, m_timeout);
-    readLen = CyaSSL_read(ssl, buf, maxLen);
-    if (readLen > 0) {
-      buf[readLen] = 0;
-      DBG("CyaSSL_read:%s\n", buf);
-    } else {
-      ERR("CyaSSL_read, ret = %d", readLen) ;
-      return HTTP_ERROR ;
+    DBG("Trying to read between %d and %d bytes", minLen, maxLen);
+    size_t readLen = 0;
+
+    if(!m_sock.is_connected()) {
+        WARN("Connection was closed by server");
+        return HTTP_CLOSED; //Connection was closed by server
+    }
+
+    int ret;
+
+    if(port == HTTPS_PORT) {
+        DBG("Enter CyaSSL_read") ;
+
+        m_sock.set_blocking(false, m_timeout);
+        readLen = CyaSSL_read(ssl, buf, maxLen);
+        if (readLen > 0) {
+            buf[readLen] = 0;
+            DBG("CyaSSL_read:%s\n", buf);
+        } else {
+            ERR("CyaSSL_read, ret = %d", readLen) ;
+            return HTTP_ERROR ;
+        }
+        DBG("Read %d bytes", readLen);
+        *pReadLen = readLen;
+        return HTTP_OK;
+    }
+
+    while(readLen < maxLen) {
+        if(readLen < minLen) {
+            DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen);
+            m_sock.set_blocking(false, m_timeout);
+            ret = m_sock.receive_all(buf + readLen, minLen - readLen);
+        } else {
+            DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen);
+            m_sock.set_blocking(false, 0);
+            ret = m_sock.receive(buf + readLen, maxLen - readLen);
+        }
+
+        if( ret > 0) {
+            readLen += ret;
+        } else if( ret == 0 ) {
+            break;
+        } else {
+            if(!m_sock.is_connected()) {
+                ERR("Connection error (recv returned %d)", ret);
+                *pReadLen = readLen;
+                return HTTP_CONN;
+            } else {
+                break;
+            }
+        }
+
+        if(!m_sock.is_connected()) {
+            break;
+        }
     }
     DBG("Read %d bytes", readLen);
     *pReadLen = readLen;
     return HTTP_OK;
-  }
-  
-  while(readLen < maxLen)
-  {
-    if(readLen < minLen)
-    {
-      DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen);
-      m_sock.set_blocking(false, m_timeout);
-      ret = m_sock.receive_all(buf + readLen, minLen - readLen);
-    }
-    else
-    {
-      DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen);
-      m_sock.set_blocking(false, 0);
-      ret = m_sock.receive(buf + readLen, maxLen - readLen);
-    }
-    
-    if( ret > 0)
-    {
-      readLen += ret;
-    } 
-    else if( ret == 0 )
-    {
-      break;
-    }
-    else
-    {
-      if(!m_sock.is_connected())
-      {
-        ERR("Connection error (recv returned %d)", ret);
-        *pReadLen = readLen;
-        return HTTP_CONN;
-      }
-      else
-      {
-        break;      
-      }
-    }
-    
-    if(!m_sock.is_connected())
-    {
-      break;
-    }
-  }
-  DBG("Read %d bytes", readLen);
-  *pReadLen = readLen;
-  return HTTP_OK;
 }
 
 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure
 {
-  HTTPResult ret ;
-  int cp_len ;
-  
-  if(len == 0)
-  {
-    len = strlen(buf);
-  }
-  
-  do {
-    if((SEND_BUF_SIZE - (send_buf_p - send_buf)) >= len){
-      cp_len = len ;
-    } else {
-      cp_len = send_buf_p - send_buf ;
+    HTTPResult ret ;
+    int cp_len ;
+
+    if(len == 0) {
+        len = strlen(buf);
     }
-    memcpy(send_buf_p, buf, cp_len) ;
-    send_buf_p += cp_len ;
-    len -= cp_len ;
 
-    if(send_buf_p == send_buf + SEND_BUF_SIZE){
-      ret = flush() ;
-      if(ret)return(ret) ;
-    }
-  } while(len) ;
-  return HTTP_OK ;
+    do {
+        if((SEND_BUF_SIZE - (send_buf_p - send_buf)) >= len) {
+            cp_len = len ;
+        } else {
+            cp_len = send_buf_p - send_buf ;
+        }
+        memcpy(send_buf_p, buf, cp_len) ;
+        send_buf_p += cp_len ;
+        len -= cp_len ;
+
+        if(send_buf_p == send_buf + SEND_BUF_SIZE) {
+            ret = flush() ;
+            if(ret)return(ret) ;
+        }
+    } while(len) ;
+    return HTTP_OK ;
 }
 
 HTTPResult HTTPClient::flush() //0 on success, err code on failure
 {
-  int len ;
-  char * buf ;
-  
-  buf = send_buf ;
-  len = send_buf_p - send_buf ;
-  send_buf_p = send_buf ; // reset send buffer
-  
-  DBG("Trying to write %d bytes:%s\n", len, buf);
-  size_t writtenLen = 0;
-    
-  if(!m_sock.is_connected())
-  {
-    WARN("Connection was closed by server");
-    return HTTP_CLOSED; //Connection was closed by server 
-  }
-  
-  if(port == HTTPS_PORT) {
-    DBG("Enter CyaSSL_write") ;
-    if (CyaSSL_write(ssl, buf, len) != len) {
-      ERR("SSL_write failed");
-      return HTTP_ERROR ;
+    int len ;
+    char * buf ;
+
+    buf = send_buf ;
+    len = send_buf_p - send_buf ;
+    send_buf_p = send_buf ; // reset send buffer
+
+    DBG("Trying to write %d bytes:%s\n", len, buf);
+    size_t writtenLen = 0;
+
+    if(!m_sock.is_connected()) {
+        WARN("Connection was closed by server");
+        return HTTP_CLOSED; //Connection was closed by server
     }
+
+    if(port == HTTPS_PORT) {
+        DBG("Enter CyaSSL_write") ;
+        if (CyaSSL_write(ssl, buf, len) != len) {
+            ERR("SSL_write failed");
+            return HTTP_ERROR ;
+        }
+        DBG("Written %d bytes", writtenLen);
+        return HTTP_OK;
+    }
+    m_sock.set_blocking(false, m_timeout);
+    int ret = m_sock.send_all(buf, len);
+    if(ret > 0) {
+        writtenLen += ret;
+    } else if( ret == 0 ) {
+        WARN("Connection was closed by server");
+        return HTTP_CLOSED; //Connection was closed by server
+    } else {
+        ERR("Connection error (send returned %d)", ret);
+        return HTTP_CONN;
+    }
+
     DBG("Written %d bytes", writtenLen);
     return HTTP_OK;
-  }
-  m_sock.set_blocking(false, m_timeout);
-  int ret = m_sock.send_all(buf, len);
-  if(ret > 0)
-  {
-    writtenLen += ret;
-  }
-  else if( ret == 0 )
-  {
-    WARN("Connection was closed by server");
-    return HTTP_CLOSED; //Connection was closed by server
-  }
-  else
-  {
-    ERR("Connection error (send returned %d)", ret);
-    return HTTP_CONN;
-  }
-  
-  DBG("Written %d bytes", writtenLen);
-  return HTTP_OK;
 }
 
 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
 {
-  char* schemePtr = (char*) url;
-  char* hostPtr = (char*) strstr(url, "://");
-  if(hostPtr == NULL)
-  {
-    WARN("Could not find host");
-    return HTTP_PARSE; //URL is invalid
-  }
+    char* schemePtr = (char*) url;
+    char* hostPtr = (char*) strstr(url, "://");
+    if(hostPtr == NULL) {
+        WARN("Could not find host");
+        return HTTP_PARSE; //URL is invalid
+    }
+
+    if( maxSchemeLen < hostPtr - schemePtr + 1 ) { //including NULL-terminating char
+        WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
+        return HTTP_PARSE;
+    }
+    memcpy(scheme, schemePtr, hostPtr - schemePtr);
+    scheme[hostPtr - schemePtr] = '\0';
 
-  if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char
-  {
-    WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
-    return HTTP_PARSE;
-  }
-  memcpy(scheme, schemePtr, hostPtr - schemePtr);
-  scheme[hostPtr - schemePtr] = '\0';
+    hostPtr+=3;
 
-  hostPtr+=3;
+    size_t hostLen = 0;
 
-  size_t hostLen = 0;
-
-  char* portPtr = strchr(hostPtr, ':');
-  if( portPtr != NULL )
-  {
-    hostLen = portPtr - hostPtr;
-    portPtr++;
-    if( sscanf(portPtr, "%hu", port) != 1)
-    {
-      WARN("Could not find port");
-      return HTTP_PARSE;
+    char* portPtr = strchr(hostPtr, ':');
+    if( portPtr != NULL ) {
+        hostLen = portPtr - hostPtr;
+        portPtr++;
+        if( sscanf(portPtr, "%hu", port) != 1) {
+            WARN("Could not find port");
+            return HTTP_PARSE;
+        }
+    } else {
+        *port=0;
     }
-  }
-  else
-  {
-    *port=0;
-  }
-  char* pathPtr = strchr(hostPtr, '/');
-  if( hostLen == 0 )
-  {
-    hostLen = pathPtr - hostPtr;
-  }
+    char* pathPtr = strchr(hostPtr, '/');
+    if( hostLen == 0 ) {
+        hostLen = pathPtr - hostPtr;
+    }
 
-  if( maxHostLen < hostLen + 1 ) //including NULL-terminating char
-  {
-    WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
-    return HTTP_PARSE;
-  }
-  memcpy(host, hostPtr, hostLen);
-  host[hostLen] = '\0';
+    if( maxHostLen < hostLen + 1 ) { //including NULL-terminating char
+        WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
+        return HTTP_PARSE;
+    }
+    memcpy(host, hostPtr, hostLen);
+    host[hostLen] = '\0';
 
-  size_t pathLen;
-  char* fragmentPtr = strchr(hostPtr, '#');
-  if(fragmentPtr != NULL)
-  {
-    pathLen = fragmentPtr - pathPtr;
-  }
-  else
-  {
-    pathLen = strlen(pathPtr);
-  }
+    size_t pathLen;
+    char* fragmentPtr = strchr(hostPtr, '#');
+    if(fragmentPtr != NULL) {
+        pathLen = fragmentPtr - pathPtr;
+    } else {
+        pathLen = strlen(pathPtr);
+    }
 
-  if( maxPathLen < pathLen + 1 ) //including NULL-terminating char
-  {
-    WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
-    return HTTP_PARSE;
-  }
-  memcpy(path, pathPtr, pathLen);
-  path[pathLen] = '\0';
+    if( maxPathLen < pathLen + 1 ) { //including NULL-terminating char
+        WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
+        return HTTP_PARSE;
+    }
+    memcpy(path, pathPtr, pathLen);
+    path[pathLen] = '\0';
 
-  return HTTP_OK;
+    return HTTP_OK;
 }