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
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
Diff: TlsMQTTClient.cpp
- 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; + } }