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

Dependencies:   SDFileSystem

Dependents:   FlashAir_Twitter Neon_F303K8_04

Fork of HTTPClient by Donatien Garnier

Revision:
20:51abf34bcc06
Parent:
19:3b1625dbd7e9
--- a/HTTPClient.cpp	Sun Dec 14 19:05:31 2014 +0000
+++ b/HTTPClient.cpp	Mon Dec 15 12:23:22 2014 +0000
@@ -18,7 +18,7 @@
  */
 
 //Debug is disabled by default
-#if 0
+#if 1
 //Enable debug
 #include <cstdio>
 #define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__);
@@ -41,15 +41,18 @@
 #define MAX(x,y) (((x)>(y))?(x):(y))
 
 #define CHUNK_SIZE 256
+#define HEADER_KEY_MAXLENGTH   64
+#define HEADER_VALUE_MAXLENGTH 128
 
 #include <cstring>
 
 #include "HTTPClient.h"
 
 HTTPClient::HTTPClient() :
-    m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
+    m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
 {
-
+    bufferPos = buffer;
+    recvCount = 0;
 }
 
 HTTPClient::~HTTPClient()
@@ -100,7 +103,6 @@
 #define CHECK_CONN_ERR(ret) \
   do{ \
     if(ret) { \
-      m_sock.close(); \
       ERR("Connection error (%d)", ret); \
       return HTTP_CONN; \
     } \
@@ -108,7 +110,6 @@
 
 #define PRTCL_ERR() \
   do{ \
-    m_sock.close(); \
     ERR("Protocol error"); \
     return HTTP_PRTCL; \
   } while(0)
@@ -125,6 +126,7 @@
 
     char scheme[8];
     uint16_t port;
+    uint16_t cmd;
     char host[32];
     char path[64];
     //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?)
@@ -137,20 +139,36 @@
     if(port == 0) { //TODO do handle HTTPS->443
         port = 80;
     }
+    if(strcmp(scheme, "http") == 0) {
+        cmd = 0x21; //SendHTTPMessageByRegister
+    } else if(strcmp(scheme, "https") == 0) {
+        cmd = 0x23; //SendHTTPSSLMessageByRegister
+    } else {
+        ERR("Not support scheme %s", scheme);
+        return HTTP_PARSE;
+    }
 
     DBG("Scheme: %s", scheme);
     DBG("Host: %s", host);
     DBG("Port: %d", port);
+    DBG("Cmd: %x", cmd);
     DBG("Path: %s", path);
 
-    //Connect
-    DBG("Connecting socket to server");
-    int ret = m_sock.connect(host, port);
-    if (ret < 0) {
-        m_sock.close();
-        ERR("Could not connect");
-        return HTTP_CONN;
-    }
+    int ret;
+
+    //Get card instance
+    card = SD_iSDIO::getInstance();
+    sequenceId = card->getSequenceId();
+
+    //Create card command
+    memset(buffer, 0, 1024);
+    bufferPos = buffer;
+    bufferPos = put_command_header(bufferPos, 1, 0);
+    bufferPos = put_command_info_header(bufferPos, cmd, sequenceId, 2);
+    bufferPos = put_str_arg(bufferPos, host);
+
+    uint8_t* bodyLenPos = bufferPos;
+    bufferPos += 4; //skip value of data size
 
     //Send request
     DBG("Sending request");
@@ -159,7 +177,6 @@
     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;
     }
@@ -244,6 +261,38 @@
         }
     }
 
+    put_u32(bodyLenPos, (bufferPos - bodyLenPos - 4));
+    put_command_header(buffer, 1, (bufferPos - buffer));
+
+#if 0
+    for (int i = 0; i < 0x400; i++) {
+        printf("%2x ", buffer[i]);
+        if ((i & 0xf) == 0xf) printf("\n");
+        if (i == 0x200-1) printf("----\n");
+    }
+    printf((char *)bodyLenPos + 4);
+    printf("\n");
+#endif
+
+    DBG("Send data size %d", (bufferPos - buffer));
+
+    if( card->writeExtDataPort(1, 1, 0x000, buffer) != true ) {
+        ERR("writeExtDataPort error (1)\n");
+        return HTTP_PRTCL;
+    }
+    if( (bufferPos - buffer) > 512 ) {
+        if( card->writeExtDataPort(1, 1, 0x000, &buffer[512]) != true ) {
+            ERR("writeExtDataPort error (2)\n");
+            return HTTP_PRTCL;
+        }
+    }
+
+    DBG("waitResponse");
+    card->waitResponse(sequenceId);
+
+    bufferPos = buffer;
+    recvCount = 0;
+
     //Receive response
     DBG("Receiving response");
     ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
@@ -285,7 +334,8 @@
         PRTCL_ERR();
     }
 
-    if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) ) {
+    //if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) ) {
+    if( (m_httpResponseCode < 100) || (m_httpResponseCode >= 600) ) {
         //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();
@@ -327,14 +377,14 @@
 
         buf[crlfPos] = '\0';
 
-        char key[32];
-        char value[32];
+        char key[HEADER_KEY_MAXLENGTH];
+        char value[HEADER_VALUE_MAXLENGTH];
 
         //key[31] = '\0';
         //value[31] = '\0';
 
-        memset(key, 0, 32);
-        memset(value, 0, 32);
+        memset(key, 0, HEADER_KEY_MAXLENGTH);
+        memset(value, 0, HEADER_VALUE_MAXLENGTH);
 
         //int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
 
@@ -343,12 +393,12 @@
         char* keyEnd = strchr(buf, ':');
         if(keyEnd != NULL) {
             *keyEnd = '\0';
-            if(strlen(buf) < 32) {
+            if(strlen(buf) < HEADER_KEY_MAXLENGTH) {
                 strcpy(key, buf);
                 n++;
                 char* valueStart = keyEnd + 2;
                 if( (valueStart - buf) < crlfPos ) {
-                    if(strlen(valueStart) < 32) {
+                    if(strlen(valueStart) < HEADER_VALUE_MAXLENGTH) {
                         strcpy(value, valueStart);
                         n++;
                     }
@@ -356,7 +406,7 @@
             }
         }
         if ( n == 2 ) {
-            DBG("Read header : %s: %s\n", key, value);
+            DBG("Read header : %s: %s", key, value);
             if( !strcmp(key, "Content-Length") ) {
                 sscanf(value, "%d", &recvContentLength);
                 recvLengthUnknown = false;
@@ -484,7 +534,6 @@
 
     }
 
-    m_sock.close();
     DBG("Completed HTTP transaction");
 
     return HTTP_OK;
@@ -495,41 +544,93 @@
     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
-    }
+    DBG("  recvCount: %d", recvCount);
+
+    if (recvCount == 0) {
 
-    int ret;
-    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);
+        // Read header and data.
+        if (!card->readExtDataPort(1, 1, 0x200, buffer)) {
+            return HTTP_PRTCL;
+        }
+#if 0
+        for (int i = 0; i < 0x200; i++) {
+            printf("%2x ", buffer[i]);
+            if ((i & 0xf) == 0xf) printf("\n");
+        }
+#endif
+        if (buffer[0] != 0x02) {
+            return HTTP_CONN;
         }
 
-        if( ret > 0) {
-            readLen += ret;
-        } else if( ret == 0 ) {
-            break;
+        recvTotalSize = get_u32(buffer + 20);
+        uint32_t recvSize = recvTotalSize > 488 ? 488 : recvTotalSize;
+        uint32_t pos = 24;
+
+        if (recvSize < maxLen) {
+            memcpy(buf, &buffer[pos], recvSize);
+            readLen = recvSize;
         } else {
-            if(!m_sock.is_connected()) {
-                ERR("Connection error (recv returned %d)", ret);
-                *pReadLen = readLen;
-                return HTTP_CONN;
+            memcpy(buf, &buffer[pos], maxLen);
+            readLen = maxLen;
+        }
+        bufferPos = &buffer[pos] + readLen;
+        recvAvailableSize = recvTotalSize - readLen;
+
+        DBG("  recvTotalSize: %d", recvTotalSize);
+        DBG("  recvAvailableSize: %d", recvAvailableSize);
+
+        recvCount++;
+
+    } else {
+
+        uint32_t recvSize = 512 - (bufferPos - buffer);
+        if (recvAvailableSize < recvSize) recvSize = recvAvailableSize;
+
+        DBG("  recvAvailableSize: %d", recvAvailableSize);
+        DBG("  recvSize: %d", recvSize);
+
+        if (recvSize > 0) {
+
+            if (recvSize < maxLen) {
+                memcpy(buf, bufferPos, recvSize);
+                readLen = recvSize;
             } else {
-                break;
+                memcpy(buf, bufferPos, maxLen);
+                readLen = maxLen;
+            }
+            bufferPos += readLen;
+            recvAvailableSize -= readLen;
+
+        } else if (recvAvailableSize > 0) {
+
+            // Read next data.
+            if (!card->readExtDataPort(1, 1, 0x200, buffer)) {
+                return HTTP_PRTCL;
             }
+#if 0
+            for (int i = 0; i < 0x200; i++) {
+                printf("%2x ", buffer[i]);
+                if ((i & 0xf) == 0xf) printf("\n");
+            }
+#endif
+            recvSize = recvAvailableSize > 512 ? 512 : recvAvailableSize;
+
+            if (recvSize < maxLen) {
+                memcpy(buf, buffer, recvSize);
+                readLen = recvSize;
+            } else {
+                memcpy(buf, buffer, maxLen);
+                readLen = maxLen;
+            }
+            bufferPos = buffer + readLen;
+            recvAvailableSize -= readLen;
+
+            recvCount++;
+
         }
 
-        if(!m_sock.is_connected()) {
-            break;
-        }
     }
+
     DBG("Read %d bytes", readLen);
     *pReadLen = readLen;
     return HTTP_OK;
@@ -543,22 +644,13 @@
     DBG("Trying to write %d bytes", len);
     size_t writtenLen = 0;
 
-    if(!m_sock.is_connected()) {
-        WARN("Connection was closed by server");
-        return HTTP_CLOSED; //Connection was closed by server
+    if(((buffer + 1024) - bufferPos) >= len) {
+        writtenLen = len;
+    } else {
+        writtenLen = ((buffer + 1024) - bufferPos);
     }
-
-    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;
-    }
+    memcpy(bufferPos, buf, writtenLen);
+    bufferPos += writtenLen;
 
     DBG("Written %d bytes", writtenLen);
     return HTTP_OK;