A HTTP/HTTPS Client for the mbed networking/CyaSSL ssl library

Dependents:   Anpi dropbox_access php_access_auth TwitterReader ... more

Fork of HTTPClient by Donatien Garnier

HTTP and HTTPS Client Class with wolfSSL, embedded SSL library.

/media/uploads/wolfSSL/wolfssl_logo.png

The class was forked from http://mbed.org/users/donatien/code/HTTPClient/

It, now, accepts url both with "http://" and "https://".

Allocate caller thread with 16kbytes or larger stack for "https" requests.

Rest of the API stays compatible with HTTPClient.

For more about the library, see http://www.wolfssl.com. http://wolfssl.com/yaSSL/Docs.html.

Extended methods:

  • HTTPResult basicAuth(const char* user, const char* password); /* set id/passwd for basic Authentication */
  • void setHeader(char *header) ; /* set http headers */
  • HTTPResult setSSLversion(int minorV) ; /* set SSL/TLS version. 0: SSL3, 1: TLS1.0, 2: TLS1.1, 3: TLS1.2 */

Files at this revision

API Documentation at this revision

Comitter:
wolfSSL
Date:
Sat Jul 12 07:11:39 2014 +0000
Parent:
21:14ecc2b2e282
Child:
24:1bef4962dd61
Commit message:
Common main.cpp for FRDM-K64F

Changed in this revision

HTTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPClient.h Show annotated file Show diff for this revision Revisions of this file
--- a/HTTPClient.cpp	Thu Apr 17 12:23:47 2014 +0000
+++ b/HTTPClient.cpp	Sat Jul 12 07:11:39 2014 +0000
@@ -62,9 +62,11 @@
     int n ;
     int i ;
 #define RECV_RETRY 3
+
     for(i=0; i<RECV_RETRY; i++) {
         n = m_sock.receive(buf, sz) ;
         if(n >= 0)return n  ;
+        wait(0.2) ;
     }
     ERR("SocketReceive:%d/%d\n", n, sz)  ;
     return n ;
@@ -73,20 +75,45 @@
 static int SocketSend(CYASSL* ssl, char *buf, int sz, void *ctx)
 {
     int n ;
-
+    
+    wait(0.1) ;
     n = m_sock.send(buf, sz);
     if(n > 0) {
+        wait(0.3) ;
         return n ;
     } else  ERR("SocketSend:%d/%d\n", n, sz);
     return n ;
 }
 
+static void base64enc(char *out, const char *in) {
+    const char code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" ;
+    int i = 0, x = 0, l = 0;
+
+    for (; *in; in++) {
+        x = x << 8 | *in;
+        for (l += 8; l >= 6; l -= 6) {
+            out[i++] = code[(x >> (l - 6)) & 0x3f];
+        }
+    }
+    if (l > 0) {
+        x <<= 6 - l;
+        out[i++] = code[x & 0x3f];
+    }
+    for (; i % 4;) {
+        out[i++] = '=';
+    }
+    out[i] = '\0' ;
+}
+
 HTTPClient::HTTPClient() :
     m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
 {
-    //CyaSSL_Debugging_ON() ;
+
+    /* CyaSSL_Debugging_ON() ; */
+    
     ctx = 0 ;
     ssl = 0 ;
+    SSLver = 3 ; 
 }
 
 HTTPClient::~HTTPClient()
@@ -94,13 +121,15 @@
 
 }
 
-#if 0
-void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
+HTTPResult HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
 {
+    #define AUTHB_SIZE 128
+    if((strlen(user) + strlen(password)) >= AUTHB_SIZE)
+        return HTTP_ERROR ;
     m_basicAuthUser = user;
     m_basicAuthPassword = password;
+    return HTTP_OK ;
 }
-#endif
 
 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
 {
@@ -139,6 +168,14 @@
     header = h ;
 }
 
+HTTPResult HTTPClient::setSSLversion(int minorV) 
+{
+    if((minorV>=0) && (minorV<=3)) 
+        SSLver = minorV ;
+    else return HTTP_ERROR ;
+    return HTTP_OK ;
+}
+
 
 #define CHECK_CONN_ERR(ret) \
   do{ \
@@ -168,11 +205,12 @@
         CyaSSL_CTX_free(ctx) ;
         ctx = NULL ;
     }
-}
-
+    CyaSSL_Cleanup() ;
+} 
 
 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request
 {
+    CYASSL_METHOD * SSLmethod ;
     m_httpResponseCode = 0; //Invalidate code
     m_timeout = timeout;
 
@@ -183,7 +221,7 @@
 
     char scheme[8];
     char host[32];
-    char path[64];
+    char path[80];
 
     int ret ;
 
@@ -194,7 +232,7 @@
         return res;
     }
 
-    if(port == 0) { //TODO do handle HTTPS->443
+    if(port == 0) {
         if(strcmp(scheme, "http") == 0)
             port = HTTP_PORT ;
         else if(strcmp(scheme, "https") == 0)
@@ -223,12 +261,17 @@
     }
 
     if(port == HTTPS_PORT) {
+
         /* Start SSL connect */
+        DBG("SSLmethod=%d", SSLmethod) ;
         if(ctx == NULL) {
-            ctx = CyaSSL_CTX_new(
-                      CyaTLSv1_2_client_method
-                      //CyaSSLv3_client_method
-                      ());
+            switch(SSLver) {
+            case 0 : SSLmethod = CyaSSLv3_client_method() ; break ;
+            case 1 : SSLmethod = CyaTLSv1_client_method() ; break ;
+            case 2 : SSLmethod = CyaTLSv1_1_client_method() ; break ;           
+            case 3 : SSLmethod = CyaTLSv1_2_client_method() ; break ;      
+            }
+            ctx = CyaSSL_CTX_new((CYASSL_METHOD *)SSLmethod);
             if (ctx == NULL) {
                 ERR("unable to get ctx");
                 return HTTP_CONN;
@@ -279,6 +322,7 @@
             CHECK_CONN_ERR(ret);
         } else {
             snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen());
+            DBG("Content buf:%s", buf) ;
             ret = send(buf);
             CHECK_CONN_ERR(ret);
         }
@@ -288,6 +332,9 @@
             ret = send(buf);
             CHECK_CONN_ERR(ret);
         }
+        if(m_basicAuthUser) {
+            bAuth() ; /* send out Basic Auth header */        
+        }
     }
 
     //Add user headers
@@ -313,15 +360,19 @@
             DBG("buf:%s", buf) ;
             if( pDataOut->getIsChunked() ) {
                 //Write chunk header
-                char chunkHeader[16];
+                char chunkHeader[64];
                 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
                 ret = send(chunkHeader);
                 CHECK_CONN_ERR(ret);
             } else if( trfLen == 0 ) {
+                DBG("trfLen==0") ;
                 break;
             }
+            DBG("trfLen 1=%d", trfLen) ;
             if( trfLen != 0 ) {
+                DBG("Sending 1") ;
                 ret = send(buf, trfLen);
+                DBG("Sent 1") ;
                 CHECK_CONN_ERR(ret);
             }
 
@@ -331,11 +382,14 @@
             } else {
                 writtenLen += trfLen;
                 if( writtenLen >= pDataOut->getDataLen() ) {
+                    DBG("writtenLen=%d", writtenLen) ;
                     break;
                 }
+                DBG("writtenLen+=trfLen = %d", writtenLen) ;
             }
-
+            DBG("trfLen 2=%d", trfLen) ;
             if( trfLen == 0 ) {
+                DBG("trfLen == 0") ;
                 break;
             }
         }
@@ -607,16 +661,22 @@
     }
 
     do {
+
         if((SEND_BUF_SIZE - (send_buf_p - send_buf)) >= len) {
             cp_len = len ;
         } else {
-            cp_len = send_buf_p - send_buf ;
+            cp_len = SEND_BUF_SIZE - (send_buf_p - send_buf) ;
         }
+        DBG("send_buf_p:%x. send_buf+SIZE:%x, len=%d, cp_len=%d", send_buf_p, send_buf+SEND_BUF_SIZE, len, cp_len) ;
         memcpy(send_buf_p, buf, cp_len) ;
         send_buf_p += cp_len ;
         len -= cp_len ;
 
         if(send_buf_p == send_buf + SEND_BUF_SIZE) {
+            if(port == HTTPS_PORT){
+                ERR("HTTPClient::send buffer overflow");
+                return HTTP_ERROR ;
+            }
             ret = flush() ;
             if(ret)return(ret) ;
         }
@@ -726,3 +786,21 @@
 
     return HTTP_OK;
 }
+
+HTTPResult HTTPClient::bAuth(void)
+{
+    HTTPResult ret ;
+    char b_auth[(int)((AUTHB_SIZE+3)*4/3+1)] ;
+    char base64buff[AUTHB_SIZE+3] ;
+ 
+    ret = send("Authorization: Basic ") ;
+    CHECK_CONN_ERR(ret);
+    sprintf(base64buff, "%s:%s", m_basicAuthUser, m_basicAuthPassword) ;
+    base64enc(b_auth, base64buff) ;
+    b_auth[strlen(b_auth)+1] = '\0' ;
+    b_auth[strlen(b_auth)] = '\n' ;
+    DBG("b_auth:%s", b_auth) ;
+    ret = send(b_auth) ;
+    CHECK_CONN_ERR(ret); 
+    return HTTP_OK ;
+}
--- a/HTTPClient.h	Thu Apr 17 12:23:47 2014 +0000
+++ b/HTTPClient.h	Sat Jul 12 07:11:39 2014 +0000
@@ -58,15 +58,13 @@
     HTTPClient();
     ~HTTPClient();
 
-#if 0 //TODO add header handlers
     /**
     Provides a basic authentification feature (Base64 encoded username and password)
     Pass two NULL pointers to switch back to no authentication
     @param user username to use for authentication, must remain valid durlng the whole HTTP session
     @param user password to use for authentication, must remain valid durlng the whole HTTP session
     */
-    void basicAuth(const char* user, const char* password); //Basic Authentification
-#endif
+    HTTPResult basicAuth(const char* user, const char* password); //Basic Authentification
 
     //High Level setup functions
     /** Execute a GET request on the URL
@@ -122,7 +120,9 @@
     @return The HTTP response code of the last request
     */
     int getHTTPResponseCode();
-    void setHeader(char *header) ;
+    
+    void setHeader(char *header) ;   /* set http headers */
+    HTTPResult setSSLversion(int minorV) ; /* set SSL/TLS version. 0: SSL3, 1: TLS1.0, 2: TLS1.1, 3: TLS1.2 */
 
 private:
     enum HTTP_METH {
@@ -139,7 +139,8 @@
     HTTPResult flush(void); //0 on success, err code on failure
     HTTPResult parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen); //Parse URL
     void cyassl_free(void) ;
-
+    HTTPResult bAuth(void) ;
+    
     //Parameters
 
     int m_timeout;
@@ -149,7 +150,9 @@
     int m_httpResponseCode;
 
     char * header ;
+
     /* for CyaSSL */
+    int    SSLver ;
     uint16_t port;
     struct CYASSL_CTX* ctx ;
     struct CYASSL    * ssl ;