HTTPClient for CyaSSL

Dependencies:   CyaSSL

Dependents:   kintone-POST kintone-POST

Fork of HTTPClient by wolf SSL

Revision:
22:4b9a4151cc73
Parent:
21:14ecc2b2e282
Child:
26:bf979804b653
--- a/HTTPClient.cpp	Thu Apr 17 12:23:47 2014 +0000
+++ b/HTTPClient.cpp	Sat Jul 12 07:08:10 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 ;
+}