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:
- 0:b32fa0c757d7
- Child:
- 1:5a896191c3c4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TlsMQTTClient.cpp Tue May 09 13:16:48 2017 +0000 @@ -0,0 +1,151 @@ +#include <cyassl/ctaocrypt/types.h> +#include "TlsMQTTClient.hpp" + +TlsMQTTClient::TlsMQTTClient() : + tcp(NULL), ctx(NULL), ssl(NULL), + mqttClient(new MQTTClient(*this)) { +} + +int TlsMQTTClient::connect(const char* host, const int port, + const char* certificates, + MQTTPacket_connectData& options) { + cleanupTransport(); + + // create TCP transport + tcp = new TCPSocketConnection(); + if (tcp->connect(host, port)) { + logError("tcp connection failed"); + goto fail; + } + + // setup SSL context + ctx = CyaSSL_CTX_new((CYASSL_METHOD *)CyaSSLv23_client_method()); + { //Localize pMethod array for less overall memory time-use + SSLMethod peerMethod = certificates != NULL ? (SSLMethod)(VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : VERIFY_NONE; + std::string pMethod; + if(peerMethod == VERIFY_NONE) { + pMethod = "not verify peer"; + } else if (peerMethod == VERIFY_PEER) { + pMethod = "verify peer if certificates available"; + //Load the CA certificate(s) (If using multiple, concatenate them in the buffer being passed) + if (SSL_SUCCESS != CyaSSL_CTX_load_verify_buffer(ctx, (const unsigned char*)certificates, strlen(certificates), SSL_FILETYPE_PEM)) { + logError("unable to load root certificates"); + goto fail; + } + } + logDebug("SSL connection set to %s", pMethod.c_str()); + CyaSSL_CTX_set_verify(ctx, peerMethod, 0); //SSL_VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_NONE, SSL_VERIFY_PEER + } + + // setup SSL operations + ssl = CyaSSL_new(ctx); + + CyaSSL_SetIOReadCtx(ssl, this); + CyaSSL_SetIORecv(ctx, ioRecv); + CyaSSL_SetIOWriteCtx(ssl, this); + CyaSSL_SetIOSend(ctx, ioSend); + + // SSL connect + { + int ret = CyaSSL_connect(ssl); + + if (ret != SSL_SUCCESS) { + logError("SSL_connect failed"); + int err = CyaSSL_get_error(ssl, ret); + char data[CYASSL_MAX_ERROR_SZ]; + char data_new[CYASSL_MAX_ERROR_SZ]; + strcpy(data_new, CyaSSL_ERR_error_string(err, data)); + if(!strcmp(data,data_new)) { + logError("Error code [%d] is [%s]\r\n", err, data); + } else { + logError("Failed to get error code [%d], Reason: [%s]\r\n", err, data_new); + } + goto fail; + } + } + + return mqttClient->connect(options); + +fail: + cleanupTransport() ; + return MQTT::FAILURE; +} + +int TlsMQTTClient::publish(const char* topicName, MQTT::Message& message) { + return mqttClient->publish(topicName, message); +} + +int TlsMQTTClient::publish(const char* topicName, void* payload, size_t payloadlen, enum MQTT::QoS qos, bool retained) { + return mqttClient->publish(topicName, payload, payloadlen, qos, retained); +} + +int TlsMQTTClient::publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum MQTT::QoS qos, bool retained) { + return mqttClient->publish(topicName, payload, payloadlen, id, qos, retained); +} + +int TlsMQTTClient::subscribe(const char* topicFilter, enum MQTT::QoS qos, MessageHandler mh) { + return mqttClient->subscribe(topicFilter, qos, mh); +} + +int TlsMQTTClient::unsubscribe(const char* topicFilter) { + return mqttClient->unsubscribe(topicFilter); +} + +int TlsMQTTClient::disconnect() { + int r = mqttClient->disconnect(); + cleanupTransport(); + return r; +} + +int TlsMQTTClient::yield(unsigned long timeout_ms) { + return mqttClient->yield(timeout_ms); +} + +bool TlsMQTTClient::isConnected() { + return mqttClient->isConnected(); +} + +void TlsMQTTClient::cleanupTransport() { + if (ssl) { + logTrace("freeing ssl"); + CyaSSL_free(ssl) ; + ssl = NULL ; + } + if (ctx) { + logTrace("freeing ssl ctx"); + CyaSSL_CTX_free(ctx) ; + ctx = NULL ; + } + if (tcp) { + if (tcp->is_connected()) { + logTrace("disconnect tcp"); + tcp->close(); + } + logTrace("freeing tcp"); + delete tcp; + tcp = NULL; + } +} + +TlsMQTTClient::~TlsMQTTClient() { + cleanupTransport(); + delete mqttClient; +} + +int TlsMQTTClient::read(unsigned char* data, int max, int timeout) { + return CyaSSL_read(ssl, data, max); +} + +int TlsMQTTClient::write(const unsigned char* data, int length, int timeout) { + return CyaSSL_write(ssl, data, length); +} + +int TlsMQTTClient::ioRecv(CYASSL* ssl, char *buf, int sz, void *ctx) { + TlsMQTTClient* thiz = (TlsMQTTClient*) ctx; + return thiz->tcp->receive(buf, sz); +} + +int TlsMQTTClient::ioSend(CYASSL* ssl, char *buf, int sz, void *ctx) { + TlsMQTTClient* thiz = (TlsMQTTClient*) ctx; + return thiz->tcp->send(buf, sz); +}