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

Committer:
pkamp
Date:
Tue Sep 19 21:45:19 2017 +0000
Revision:
10:e9abab84df23
Parent:
9:2d119fbe7482
Adding publishing

Who changed what in which revision?

UserRevisionLine numberNew contents of line
miaotwilio 0:b32fa0c757d7 1 #include <cyassl/ctaocrypt/types.h>
miaotwilio 0:b32fa0c757d7 2 #include "TlsMQTTClient.hpp"
miaotwilio 0:b32fa0c757d7 3
pkamp 9:2d119fbe7482 4
miaotwilio 0:b32fa0c757d7 5 TlsMQTTClient::TlsMQTTClient() :
miaotwilio 0:b32fa0c757d7 6 tcp(NULL), ctx(NULL), ssl(NULL),
miaotwilio 0:b32fa0c757d7 7 mqttClient(new MQTTClient(*this)) {
miaotwilio 0:b32fa0c757d7 8 }
miaotwilio 0:b32fa0c757d7 9
pkamp 9:2d119fbe7482 10
pkamp 9:2d119fbe7482 11 int TlsMQTTClient::connect(
pkamp 9:2d119fbe7482 12 const char* host,
pkamp 9:2d119fbe7482 13 const int port,
pkamp 9:2d119fbe7482 14 const char* certificates,
pkamp 9:2d119fbe7482 15 MQTTPacket_connectData& options
pkamp 9:2d119fbe7482 16 )
pkamp 9:2d119fbe7482 17 {
miaotwilio 0:b32fa0c757d7 18 cleanupTransport();
miaotwilio 0:b32fa0c757d7 19
miaotwilio 0:b32fa0c757d7 20 // create TCP transport
miaotwilio 0:b32fa0c757d7 21 tcp = new TCPSocketConnection();
miaotwilio 0:b32fa0c757d7 22 if (tcp->connect(host, port)) {
miaotwilio 0:b32fa0c757d7 23 logError("tcp connection failed");
miaotwilio 0:b32fa0c757d7 24 goto fail;
miaotwilio 0:b32fa0c757d7 25 }
miaotwilio 1:5a896191c3c4 26 tcp->set_blocking(false, 50);
miaotwilio 0:b32fa0c757d7 27
miaotwilio 0:b32fa0c757d7 28 // setup SSL context
miaotwilio 0:b32fa0c757d7 29 ctx = CyaSSL_CTX_new((CYASSL_METHOD *)CyaSSLv23_client_method());
miaotwilio 0:b32fa0c757d7 30 { //Localize pMethod array for less overall memory time-use
pkamp 9:2d119fbe7482 31 SSLMethod peerMethod = certificates != \
pkamp 9:2d119fbe7482 32 NULL ? (SSLMethod)(
pkamp 9:2d119fbe7482 33 VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT
pkamp 9:2d119fbe7482 34 ) : VERIFY_NONE;
pkamp 9:2d119fbe7482 35
miaotwilio 0:b32fa0c757d7 36 std::string pMethod;
miaotwilio 0:b32fa0c757d7 37 if(peerMethod == VERIFY_NONE) {
miaotwilio 0:b32fa0c757d7 38 pMethod = "not verify peer";
miaotwilio 3:0a48c984e15b 39 } else if (peerMethod & VERIFY_PEER) {
pkamp 9:2d119fbe7482 40 pMethod = "Verify peer if certificates available";
pkamp 9:2d119fbe7482 41 //Load the CA certificate(s)
pkamp 9:2d119fbe7482 42 // (If using multiple, concatenate them in the buffer being passed)
pkamp 9:2d119fbe7482 43 if (SSL_SUCCESS != CyaSSL_CTX_load_verify_buffer(
pkamp 9:2d119fbe7482 44 ctx,
pkamp 9:2d119fbe7482 45 (const unsigned char*)certificates,
pkamp 9:2d119fbe7482 46 strlen(certificates),
pkamp 9:2d119fbe7482 47 SSL_FILETYPE_PEM)
pkamp 9:2d119fbe7482 48 ) {
pkamp 9:2d119fbe7482 49
pkamp 9:2d119fbe7482 50 logError("Unable to load root certificates!");
miaotwilio 0:b32fa0c757d7 51 goto fail;
miaotwilio 0:b32fa0c757d7 52 }
miaotwilio 0:b32fa0c757d7 53 }
miaotwilio 0:b32fa0c757d7 54 logDebug("SSL connection set to %s", pMethod.c_str());
pkamp 9:2d119fbe7482 55
pkamp 9:2d119fbe7482 56 //SSL_VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_NONE, SSL_VERIFY_PEER
pkamp 9:2d119fbe7482 57 CyaSSL_CTX_set_verify(ctx, peerMethod, 0);
miaotwilio 0:b32fa0c757d7 58 }
miaotwilio 0:b32fa0c757d7 59
miaotwilio 0:b32fa0c757d7 60 // setup SSL operations
miaotwilio 0:b32fa0c757d7 61 ssl = CyaSSL_new(ctx);
miaotwilio 0:b32fa0c757d7 62
miaotwilio 1:5a896191c3c4 63 CyaSSL_set_using_nonblock(ssl, 1);
miaotwilio 0:b32fa0c757d7 64 CyaSSL_SetIOReadCtx(ssl, this);
miaotwilio 0:b32fa0c757d7 65 CyaSSL_SetIORecv(ctx, ioRecv);
miaotwilio 0:b32fa0c757d7 66 CyaSSL_SetIOWriteCtx(ssl, this);
miaotwilio 0:b32fa0c757d7 67 CyaSSL_SetIOSend(ctx, ioSend);
miaotwilio 0:b32fa0c757d7 68
miaotwilio 0:b32fa0c757d7 69 // SSL connect
miaotwilio 1:5a896191c3c4 70 while (true) {
miaotwilio 0:b32fa0c757d7 71 int ret = CyaSSL_connect(ssl);
miaotwilio 1:5a896191c3c4 72
miaotwilio 1:5a896191c3c4 73 if (ret != SSL_SUCCESS) {
miaotwilio 1:5a896191c3c4 74 int err = CyaSSL_get_error(ssl, ret);
miaotwilio 0:b32fa0c757d7 75
miaotwilio 1:5a896191c3c4 76 if (SSL_ERROR_WANT_READ == err ||
miaotwilio 1:5a896191c3c4 77 SSL_ERROR_WANT_WRITE == err) {
miaotwilio 1:5a896191c3c4 78 continue;
miaotwilio 1:5a896191c3c4 79 }
miaotwilio 1:5a896191c3c4 80
miaotwilio 1:5a896191c3c4 81 logError("SSL_connect failed ret %d", ret);
miaotwilio 1:5a896191c3c4 82
miaotwilio 0:b32fa0c757d7 83 char data[CYASSL_MAX_ERROR_SZ];
miaotwilio 0:b32fa0c757d7 84 char data_new[CYASSL_MAX_ERROR_SZ];
miaotwilio 0:b32fa0c757d7 85 strcpy(data_new, CyaSSL_ERR_error_string(err, data));
miaotwilio 0:b32fa0c757d7 86 if(!strcmp(data,data_new)) {
miaotwilio 0:b32fa0c757d7 87 logError("Error code [%d] is [%s]\r\n", err, data);
miaotwilio 0:b32fa0c757d7 88 } else {
pkamp 9:2d119fbe7482 89 logError(
pkamp 9:2d119fbe7482 90 "Failed to get error code [%d], Reason: [%s]\r\n",
pkamp 9:2d119fbe7482 91 err,
pkamp 9:2d119fbe7482 92 data_new
pkamp 9:2d119fbe7482 93 );
miaotwilio 0:b32fa0c757d7 94 }
miaotwilio 1:5a896191c3c4 95
miaotwilio 0:b32fa0c757d7 96 goto fail;
miaotwilio 1:5a896191c3c4 97 } else {
miaotwilio 1:5a896191c3c4 98 break;
miaotwilio 0:b32fa0c757d7 99 }
miaotwilio 0:b32fa0c757d7 100 }
miaotwilio 0:b32fa0c757d7 101
miaotwilio 0:b32fa0c757d7 102 return mqttClient->connect(options);
miaotwilio 0:b32fa0c757d7 103
pkamp 9:2d119fbe7482 104 // Cleanup handler
miaotwilio 0:b32fa0c757d7 105 fail:
miaotwilio 0:b32fa0c757d7 106 cleanupTransport() ;
miaotwilio 0:b32fa0c757d7 107 return MQTT::FAILURE;
miaotwilio 0:b32fa0c757d7 108 }
miaotwilio 0:b32fa0c757d7 109
pkamp 9:2d119fbe7482 110 int TlsMQTTClient::publish(const char* topicName, MQTT::Message& message)
pkamp 9:2d119fbe7482 111 {
miaotwilio 0:b32fa0c757d7 112 return mqttClient->publish(topicName, message);
miaotwilio 0:b32fa0c757d7 113 }
miaotwilio 0:b32fa0c757d7 114
pkamp 9:2d119fbe7482 115 int TlsMQTTClient::publish(
pkamp 9:2d119fbe7482 116 const char* topicName,
pkamp 9:2d119fbe7482 117 void* payload,
pkamp 9:2d119fbe7482 118 size_t payloadlen,
pkamp 9:2d119fbe7482 119 enum MQTT::QoS qos,
pkamp 9:2d119fbe7482 120 bool retained
pkamp 9:2d119fbe7482 121 )
pkamp 9:2d119fbe7482 122 {
miaotwilio 0:b32fa0c757d7 123 return mqttClient->publish(topicName, payload, payloadlen, qos, retained);
miaotwilio 0:b32fa0c757d7 124 }
miaotwilio 0:b32fa0c757d7 125
pkamp 9:2d119fbe7482 126 int TlsMQTTClient::publish(
pkamp 9:2d119fbe7482 127 const char* topicName,
pkamp 9:2d119fbe7482 128 void* payload, size_t payloadlen,
pkamp 9:2d119fbe7482 129 unsigned short& id,
pkamp 9:2d119fbe7482 130 enum MQTT::QoS qos,
pkamp 9:2d119fbe7482 131 bool retained
pkamp 9:2d119fbe7482 132 )
pkamp 9:2d119fbe7482 133 {
pkamp 9:2d119fbe7482 134 return mqttClient->publish(
pkamp 9:2d119fbe7482 135 topicName,
pkamp 9:2d119fbe7482 136 payload,
pkamp 9:2d119fbe7482 137 payloadlen,
pkamp 9:2d119fbe7482 138 id,
pkamp 9:2d119fbe7482 139 qos,
pkamp 9:2d119fbe7482 140 retained
pkamp 9:2d119fbe7482 141 );
miaotwilio 0:b32fa0c757d7 142 }
miaotwilio 0:b32fa0c757d7 143
pkamp 9:2d119fbe7482 144 int TlsMQTTClient::subscribe(
pkamp 9:2d119fbe7482 145 const char* topicFilter,
pkamp 9:2d119fbe7482 146 enum MQTT::QoS qos,
pkamp 9:2d119fbe7482 147 MessageHandler mh
pkamp 9:2d119fbe7482 148 )
pkamp 9:2d119fbe7482 149 {
miaotwilio 0:b32fa0c757d7 150 return mqttClient->subscribe(topicFilter, qos, mh);
miaotwilio 0:b32fa0c757d7 151 }
miaotwilio 0:b32fa0c757d7 152
pkamp 9:2d119fbe7482 153 int TlsMQTTClient::unsubscribe(const char* topicFilter)
pkamp 9:2d119fbe7482 154 {
miaotwilio 0:b32fa0c757d7 155 return mqttClient->unsubscribe(topicFilter);
miaotwilio 0:b32fa0c757d7 156 }
miaotwilio 0:b32fa0c757d7 157
pkamp 9:2d119fbe7482 158 int TlsMQTTClient::disconnect()
pkamp 9:2d119fbe7482 159 {
miaotwilio 0:b32fa0c757d7 160 int r = mqttClient->disconnect();
miaotwilio 0:b32fa0c757d7 161 cleanupTransport();
miaotwilio 0:b32fa0c757d7 162 return r;
miaotwilio 0:b32fa0c757d7 163 }
miaotwilio 0:b32fa0c757d7 164
pkamp 9:2d119fbe7482 165 int TlsMQTTClient::yield(unsigned long timeout_ms)
pkamp 9:2d119fbe7482 166 {
miaotwilio 0:b32fa0c757d7 167 return mqttClient->yield(timeout_ms);
miaotwilio 0:b32fa0c757d7 168 }
miaotwilio 0:b32fa0c757d7 169
pkamp 9:2d119fbe7482 170 bool TlsMQTTClient::isConnected()
pkamp 9:2d119fbe7482 171 {
miaotwilio 0:b32fa0c757d7 172 return mqttClient->isConnected();
miaotwilio 0:b32fa0c757d7 173 }
miaotwilio 0:b32fa0c757d7 174
miaotwilio 0:b32fa0c757d7 175 void TlsMQTTClient::cleanupTransport() {
miaotwilio 0:b32fa0c757d7 176 if (ssl) {
miaotwilio 0:b32fa0c757d7 177 logTrace("freeing ssl");
miaotwilio 0:b32fa0c757d7 178 CyaSSL_free(ssl) ;
miaotwilio 0:b32fa0c757d7 179 ssl = NULL ;
miaotwilio 0:b32fa0c757d7 180 }
miaotwilio 0:b32fa0c757d7 181 if (ctx) {
miaotwilio 0:b32fa0c757d7 182 logTrace("freeing ssl ctx");
miaotwilio 0:b32fa0c757d7 183 CyaSSL_CTX_free(ctx) ;
miaotwilio 0:b32fa0c757d7 184 ctx = NULL ;
miaotwilio 0:b32fa0c757d7 185 }
miaotwilio 0:b32fa0c757d7 186 if (tcp) {
miaotwilio 0:b32fa0c757d7 187 if (tcp->is_connected()) {
miaotwilio 0:b32fa0c757d7 188 logTrace("disconnect tcp");
miaotwilio 0:b32fa0c757d7 189 tcp->close();
miaotwilio 0:b32fa0c757d7 190 }
miaotwilio 0:b32fa0c757d7 191 logTrace("freeing tcp");
miaotwilio 0:b32fa0c757d7 192 delete tcp;
miaotwilio 0:b32fa0c757d7 193 tcp = NULL;
miaotwilio 0:b32fa0c757d7 194 }
miaotwilio 0:b32fa0c757d7 195 }
miaotwilio 0:b32fa0c757d7 196
miaotwilio 0:b32fa0c757d7 197 TlsMQTTClient::~TlsMQTTClient() {
miaotwilio 0:b32fa0c757d7 198 cleanupTransport();
miaotwilio 0:b32fa0c757d7 199 delete mqttClient;
miaotwilio 0:b32fa0c757d7 200 }
miaotwilio 0:b32fa0c757d7 201
pkamp 9:2d119fbe7482 202 int TlsMQTTClient::read(
pkamp 9:2d119fbe7482 203 unsigned char* data,
pkamp 9:2d119fbe7482 204 int max,
pkamp 9:2d119fbe7482 205 int timeout
pkamp 9:2d119fbe7482 206 )
pkamp 9:2d119fbe7482 207 {
pkamp 9:2d119fbe7482 208 // logTrace(
pkamp 9:2d119fbe7482 209 // "TlsMQTTClient::read data %p max %d timeout %d",
pkamp 9:2d119fbe7482 210 // data,
pkamp 9:2d119fbe7482 211 // max,
pkamp 9:2d119fbe7482 212 // timeout
pkamp 9:2d119fbe7482 213 // );
miaotwilio 1:5a896191c3c4 214 Timer tmr;
miaotwilio 1:5a896191c3c4 215 int bytes = 0;
miaotwilio 1:5a896191c3c4 216 int totalbytes = 0;
miaotwilio 1:5a896191c3c4 217
miaotwilio 1:5a896191c3c4 218 tmr.start();
miaotwilio 1:5a896191c3c4 219 do {
miaotwilio 1:5a896191c3c4 220 bytes = CyaSSL_read(ssl, data, max);
miaotwilio 1:5a896191c3c4 221 if (bytes < 0) {
miaotwilio 1:5a896191c3c4 222 int err = CyaSSL_get_error(ssl, bytes);
miaotwilio 1:5a896191c3c4 223 if (SSL_ERROR_WANT_READ == err) {
miaotwilio 1:5a896191c3c4 224 continue;
miaotwilio 1:5a896191c3c4 225 }
miaotwilio 1:5a896191c3c4 226 logTrace("CyaSSL_read fail %d", err);
miaotwilio 1:5a896191c3c4 227 return -1;
miaotwilio 1:5a896191c3c4 228 }
miaotwilio 1:5a896191c3c4 229 totalbytes += bytes;
miaotwilio 1:5a896191c3c4 230 } while ( tmr.read_ms() < timeout && totalbytes < max);
miaotwilio 1:5a896191c3c4 231 //logTrace("TlsMQTTClient::read totalbytes %d", totalbytes);
miaotwilio 1:5a896191c3c4 232 return totalbytes;
miaotwilio 0:b32fa0c757d7 233 }
miaotwilio 0:b32fa0c757d7 234
miaotwilio 0:b32fa0c757d7 235 int TlsMQTTClient::write(const unsigned char* data, int length, int timeout) {
pkamp 9:2d119fbe7482 236 // logTrace(
pkamp 9:2d119fbe7482 237 // "TlsMQTTClient::write data %p max %d timeout %d",
pkamp 9:2d119fbe7482 238 // data,
pkamp 9:2d119fbe7482 239 // length,
pkamp 9:2d119fbe7482 240 // timeout
pkamp 9:2d119fbe7482 241 // );
miaotwilio 1:5a896191c3c4 242 Timer tmr;
miaotwilio 1:5a896191c3c4 243 int bytes = 0;
miaotwilio 1:5a896191c3c4 244 int totalbytes = 0;
miaotwilio 1:5a896191c3c4 245
miaotwilio 1:5a896191c3c4 246 tmr.start();
miaotwilio 1:5a896191c3c4 247 do {
miaotwilio 1:5a896191c3c4 248 bytes = CyaSSL_write(ssl, data, length);
miaotwilio 1:5a896191c3c4 249 if (bytes < 0) {
miaotwilio 1:5a896191c3c4 250 int err = CyaSSL_get_error(ssl, bytes);
miaotwilio 1:5a896191c3c4 251 if (SSL_ERROR_WANT_WRITE == err) {
miaotwilio 1:5a896191c3c4 252 continue;
miaotwilio 1:5a896191c3c4 253 }
miaotwilio 1:5a896191c3c4 254 logTrace("CyaSSL_write fail %d", err);
miaotwilio 1:5a896191c3c4 255 return -1;
miaotwilio 1:5a896191c3c4 256 }
miaotwilio 1:5a896191c3c4 257 totalbytes += bytes;
miaotwilio 1:5a896191c3c4 258 } while (tmr.read_ms() < timeout && totalbytes < length);
miaotwilio 1:5a896191c3c4 259 //logTrace("TlsMQTTClient::write totalbytes %d", totalbytes);
miaotwilio 1:5a896191c3c4 260 return totalbytes;
miaotwilio 0:b32fa0c757d7 261 }
miaotwilio 0:b32fa0c757d7 262
miaotwilio 0:b32fa0c757d7 263 int TlsMQTTClient::ioRecv(CYASSL* ssl, char *buf, int sz, void *ctx) {
miaotwilio 0:b32fa0c757d7 264 TlsMQTTClient* thiz = (TlsMQTTClient*) ctx;
miaotwilio 1:5a896191c3c4 265 int n = thiz->tcp->receive(buf, sz);
miaotwilio 1:5a896191c3c4 266 if (0 == n) {
miaotwilio 1:5a896191c3c4 267 return CYASSL_CBIO_ERR_WANT_READ;
miaotwilio 1:5a896191c3c4 268 } else if (n > 0) {
miaotwilio 1:5a896191c3c4 269 return n;
miaotwilio 1:5a896191c3c4 270 } else {
miaotwilio 1:5a896191c3c4 271 return CYASSL_CBIO_ERR_GENERAL;
miaotwilio 1:5a896191c3c4 272 }
miaotwilio 0:b32fa0c757d7 273 }
miaotwilio 0:b32fa0c757d7 274
miaotwilio 0:b32fa0c757d7 275 int TlsMQTTClient::ioSend(CYASSL* ssl, char *buf, int sz, void *ctx) {
miaotwilio 0:b32fa0c757d7 276 TlsMQTTClient* thiz = (TlsMQTTClient*) ctx;
miaotwilio 1:5a896191c3c4 277 int n = thiz->tcp->send(buf, sz);
miaotwilio 1:5a896191c3c4 278 if (0 == n) {
miaotwilio 1:5a896191c3c4 279 return CYASSL_CBIO_ERR_WANT_WRITE;
miaotwilio 1:5a896191c3c4 280 } else if (n > 0) {
miaotwilio 1:5a896191c3c4 281 return n;
miaotwilio 1:5a896191c3c4 282 } else {
miaotwilio 1:5a896191c3c4 283 return CYASSL_CBIO_ERR_GENERAL;
miaotwilio 1:5a896191c3c4 284 }
miaotwilio 0:b32fa0c757d7 285 }