Connecting a Multi-Tech Systems Dragonfly™ to Twilio's Sync for IoT Quickstart. Blink a dev board LED.

Dependencies:   MQTT MbedJSONValue mbed mtsas

Fork of DragonflyMQTT by miao zhicheng

Code to connect a Multi-Tech® MultiConnect® Dragonfly™ to Twilio's Sync for IoT: https://www.twilio.com/docs/api/devices

Uses MQTT over TLS and subscribes to a topic where you can control an LED. See also our Quickstart using this code, here: https://www.twilio.com/docs/quickstart/sync-iot/mqtt-multi-tech-multiconnect-dragonfly-sync-iot

Revision:
1:5a896191c3c4
Parent:
0:b32fa0c757d7
Child:
3:0a48c984e15b
--- a/TlsMQTTClient.cpp	Tue May 09 13:16:48 2017 +0000
+++ b/TlsMQTTClient.cpp	Fri May 12 11:49:58 2017 +0000
@@ -17,6 +17,7 @@
         logError("tcp connection failed");
         goto fail;
     }
+    tcp->set_blocking(false, 50);
 
     // setup SSL context
     ctx = CyaSSL_CTX_new((CYASSL_METHOD *)CyaSSLv23_client_method());
@@ -40,18 +41,26 @@
     // setup SSL operations
     ssl = CyaSSL_new(ctx);
 
+    CyaSSL_set_using_nonblock(ssl, 1);
     CyaSSL_SetIOReadCtx(ssl, this);
     CyaSSL_SetIORecv(ctx, ioRecv);
     CyaSSL_SetIOWriteCtx(ssl, this);
     CyaSSL_SetIOSend(ctx, ioSend);
 
     // SSL connect
-    {
+    while (true) {
         int ret = CyaSSL_connect(ssl);
+
+        if (ret != SSL_SUCCESS) {
+            int err = CyaSSL_get_error(ssl, ret);
     
-        if (ret != SSL_SUCCESS) {
-            logError("SSL_connect failed");
-            int err = CyaSSL_get_error(ssl, ret);
+            if (SSL_ERROR_WANT_READ == err ||
+                SSL_ERROR_WANT_WRITE == err) {
+                continue;
+            }
+
+            logError("SSL_connect failed ret %d", ret);
+
             char data[CYASSL_MAX_ERROR_SZ];
             char data_new[CYASSL_MAX_ERROR_SZ];
             strcpy(data_new, CyaSSL_ERR_error_string(err, data));
@@ -60,7 +69,10 @@
             } else {
                 logError("Failed to get error code [%d], Reason: [%s]\r\n", err, data_new);
             }
+
             goto fail;
+        } else {
+            break;
         }
     }
 
@@ -133,19 +145,71 @@
 }
 
 int TlsMQTTClient::read(unsigned char* data, int max, int timeout) {
-    return CyaSSL_read(ssl, data, max);
+    //logTrace("TlsMQTTClient::read data %p max %d timeout %d", data, max, timeout);
+    Timer tmr;
+    int bytes = 0;    
+    int totalbytes = 0;
+    
+    tmr.start();
+    do {
+        bytes = CyaSSL_read(ssl, data, max);
+        if (bytes < 0) {
+            int err = CyaSSL_get_error(ssl, bytes);
+            if (SSL_ERROR_WANT_READ == err) {
+                continue;
+            }
+            logTrace("CyaSSL_read fail %d", err);
+            return -1;
+        }
+        totalbytes += bytes;
+    } while ( tmr.read_ms() < timeout && totalbytes < max);
+    //logTrace("TlsMQTTClient::read totalbytes %d", totalbytes);
+    return totalbytes;
 }
 
 int TlsMQTTClient::write(const unsigned char* data, int length, int timeout) {
-    return CyaSSL_write(ssl, data, length);
+    //logTrace("TlsMQTTClient::write data %p max %d timeout %d", data, length, timeout);
+    Timer tmr;
+    int bytes = 0;    
+    int totalbytes = 0;
+    
+    tmr.start();
+    do {
+        bytes = CyaSSL_write(ssl, data, length);
+        if (bytes < 0) {
+            int err = CyaSSL_get_error(ssl, bytes);
+            if (SSL_ERROR_WANT_WRITE == err) {
+                continue;
+            }
+            logTrace("CyaSSL_write fail %d", err);
+            return -1;
+        }
+        totalbytes += bytes;
+    } while (tmr.read_ms() < timeout && totalbytes < length);
+    //logTrace("TlsMQTTClient::write totalbytes %d", totalbytes);
+    return totalbytes;
 }
 
 int TlsMQTTClient::ioRecv(CYASSL* ssl, char *buf, int sz, void *ctx) {
     TlsMQTTClient* thiz = (TlsMQTTClient*) ctx;
-    return thiz->tcp->receive(buf, sz);
+    int n = thiz->tcp->receive(buf, sz);
+    if (0 == n) {
+        return CYASSL_CBIO_ERR_WANT_READ;
+    } else if (n > 0) {
+        return n;
+    } else {
+        return CYASSL_CBIO_ERR_GENERAL;
+    }
 }
 
 int TlsMQTTClient::ioSend(CYASSL* ssl, char *buf, int sz, void *ctx) {
     TlsMQTTClient* thiz = (TlsMQTTClient*) ctx;
-    return thiz->tcp->send(buf, sz);
+    int n = thiz->tcp->send(buf, sz);
+    if (0 == n) {
+        return CYASSL_CBIO_ERR_WANT_WRITE;
+    } else if (n > 0) {
+        return n;
+    } else {
+        return CYASSL_CBIO_ERR_GENERAL;
+    }
 }