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
TlsMQTTClient.cpp
00001 #include <cyassl/ctaocrypt/types.h> 00002 #include "TlsMQTTClient.hpp" 00003 00004 00005 TlsMQTTClient::TlsMQTTClient() : 00006 tcp(NULL), ctx(NULL), ssl(NULL), 00007 mqttClient(new MQTTClient(*this)) { 00008 } 00009 00010 00011 int TlsMQTTClient::connect( 00012 const char* host, 00013 const int port, 00014 const char* certificates, 00015 MQTTPacket_connectData& options 00016 ) 00017 { 00018 cleanupTransport(); 00019 00020 // create TCP transport 00021 tcp = new TCPSocketConnection(); 00022 if (tcp->connect(host, port)) { 00023 logError("tcp connection failed"); 00024 goto fail; 00025 } 00026 tcp->set_blocking(false, 50); 00027 00028 // setup SSL context 00029 ctx = CyaSSL_CTX_new((CYASSL_METHOD *)CyaSSLv23_client_method()); 00030 { //Localize pMethod array for less overall memory time-use 00031 SSLMethod peerMethod = certificates != \ 00032 NULL ? (SSLMethod)( 00033 VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT 00034 ) : VERIFY_NONE; 00035 00036 std::string pMethod; 00037 if(peerMethod == VERIFY_NONE) { 00038 pMethod = "not verify peer"; 00039 } else if (peerMethod & VERIFY_PEER) { 00040 pMethod = "Verify peer if certificates available"; 00041 //Load the CA certificate(s) 00042 // (If using multiple, concatenate them in the buffer being passed) 00043 if (SSL_SUCCESS != CyaSSL_CTX_load_verify_buffer( 00044 ctx, 00045 (const unsigned char*)certificates, 00046 strlen(certificates), 00047 SSL_FILETYPE_PEM) 00048 ) { 00049 00050 logError("Unable to load root certificates!"); 00051 goto fail; 00052 } 00053 } 00054 logDebug("SSL connection set to %s", pMethod.c_str()); 00055 00056 //SSL_VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_NONE, SSL_VERIFY_PEER 00057 CyaSSL_CTX_set_verify(ctx, peerMethod, 0); 00058 } 00059 00060 // setup SSL operations 00061 ssl = CyaSSL_new(ctx); 00062 00063 CyaSSL_set_using_nonblock(ssl, 1); 00064 CyaSSL_SetIOReadCtx(ssl, this); 00065 CyaSSL_SetIORecv(ctx, ioRecv); 00066 CyaSSL_SetIOWriteCtx(ssl, this); 00067 CyaSSL_SetIOSend(ctx, ioSend); 00068 00069 // SSL connect 00070 while (true) { 00071 int ret = CyaSSL_connect(ssl); 00072 00073 if (ret != SSL_SUCCESS) { 00074 int err = CyaSSL_get_error(ssl, ret); 00075 00076 if (SSL_ERROR_WANT_READ == err || 00077 SSL_ERROR_WANT_WRITE == err) { 00078 continue; 00079 } 00080 00081 logError("SSL_connect failed ret %d", ret); 00082 00083 char data[CYASSL_MAX_ERROR_SZ]; 00084 char data_new[CYASSL_MAX_ERROR_SZ]; 00085 strcpy(data_new, CyaSSL_ERR_error_string(err, data)); 00086 if(!strcmp(data,data_new)) { 00087 logError("Error code [%d] is [%s]\r\n", err, data); 00088 } else { 00089 logError( 00090 "Failed to get error code [%d], Reason: [%s]\r\n", 00091 err, 00092 data_new 00093 ); 00094 } 00095 00096 goto fail; 00097 } else { 00098 break; 00099 } 00100 } 00101 00102 return mqttClient->connect(options); 00103 00104 // Cleanup handler 00105 fail: 00106 cleanupTransport() ; 00107 return MQTT::FAILURE; 00108 } 00109 00110 int TlsMQTTClient::publish(const char* topicName, MQTT::Message& message) 00111 { 00112 return mqttClient->publish(topicName, message); 00113 } 00114 00115 int TlsMQTTClient::publish( 00116 const char* topicName, 00117 void* payload, 00118 size_t payloadlen, 00119 enum MQTT::QoS qos, 00120 bool retained 00121 ) 00122 { 00123 return mqttClient->publish(topicName, payload, payloadlen, qos, retained); 00124 } 00125 00126 int TlsMQTTClient::publish( 00127 const char* topicName, 00128 void* payload, size_t payloadlen, 00129 unsigned short& id, 00130 enum MQTT::QoS qos, 00131 bool retained 00132 ) 00133 { 00134 return mqttClient->publish( 00135 topicName, 00136 payload, 00137 payloadlen, 00138 id, 00139 qos, 00140 retained 00141 ); 00142 } 00143 00144 int TlsMQTTClient::subscribe( 00145 const char* topicFilter, 00146 enum MQTT::QoS qos, 00147 MessageHandler mh 00148 ) 00149 { 00150 return mqttClient->subscribe(topicFilter, qos, mh); 00151 } 00152 00153 int TlsMQTTClient::unsubscribe(const char* topicFilter) 00154 { 00155 return mqttClient->unsubscribe(topicFilter); 00156 } 00157 00158 int TlsMQTTClient::disconnect() 00159 { 00160 int r = mqttClient->disconnect(); 00161 cleanupTransport(); 00162 return r; 00163 } 00164 00165 int TlsMQTTClient::yield(unsigned long timeout_ms) 00166 { 00167 return mqttClient->yield(timeout_ms); 00168 } 00169 00170 bool TlsMQTTClient::isConnected() 00171 { 00172 return mqttClient->isConnected(); 00173 } 00174 00175 void TlsMQTTClient::cleanupTransport() { 00176 if (ssl) { 00177 logTrace("freeing ssl"); 00178 CyaSSL_free(ssl) ; 00179 ssl = NULL ; 00180 } 00181 if (ctx) { 00182 logTrace("freeing ssl ctx"); 00183 CyaSSL_CTX_free(ctx) ; 00184 ctx = NULL ; 00185 } 00186 if (tcp) { 00187 if (tcp->is_connected()) { 00188 logTrace("disconnect tcp"); 00189 tcp->close(); 00190 } 00191 logTrace("freeing tcp"); 00192 delete tcp; 00193 tcp = NULL; 00194 } 00195 } 00196 00197 TlsMQTTClient::~TlsMQTTClient() { 00198 cleanupTransport(); 00199 delete mqttClient; 00200 } 00201 00202 int TlsMQTTClient::read( 00203 unsigned char* data, 00204 int max, 00205 int timeout 00206 ) 00207 { 00208 // logTrace( 00209 // "TlsMQTTClient::read data %p max %d timeout %d", 00210 // data, 00211 // max, 00212 // timeout 00213 // ); 00214 Timer tmr; 00215 int bytes = 0; 00216 int totalbytes = 0; 00217 00218 tmr.start(); 00219 do { 00220 bytes = CyaSSL_read(ssl, data, max); 00221 if (bytes < 0) { 00222 int err = CyaSSL_get_error(ssl, bytes); 00223 if (SSL_ERROR_WANT_READ == err) { 00224 continue; 00225 } 00226 logTrace("CyaSSL_read fail %d", err); 00227 return -1; 00228 } 00229 totalbytes += bytes; 00230 } while ( tmr.read_ms() < timeout && totalbytes < max); 00231 //logTrace("TlsMQTTClient::read totalbytes %d", totalbytes); 00232 return totalbytes; 00233 } 00234 00235 int TlsMQTTClient::write(const unsigned char* data, int length, int timeout) { 00236 // logTrace( 00237 // "TlsMQTTClient::write data %p max %d timeout %d", 00238 // data, 00239 // length, 00240 // timeout 00241 // ); 00242 Timer tmr; 00243 int bytes = 0; 00244 int totalbytes = 0; 00245 00246 tmr.start(); 00247 do { 00248 bytes = CyaSSL_write(ssl, data, length); 00249 if (bytes < 0) { 00250 int err = CyaSSL_get_error(ssl, bytes); 00251 if (SSL_ERROR_WANT_WRITE == err) { 00252 continue; 00253 } 00254 logTrace("CyaSSL_write fail %d", err); 00255 return -1; 00256 } 00257 totalbytes += bytes; 00258 } while (tmr.read_ms() < timeout && totalbytes < length); 00259 //logTrace("TlsMQTTClient::write totalbytes %d", totalbytes); 00260 return totalbytes; 00261 } 00262 00263 int TlsMQTTClient::ioRecv(CYASSL* ssl, char *buf, int sz, void *ctx) { 00264 TlsMQTTClient* thiz = (TlsMQTTClient*) ctx; 00265 int n = thiz->tcp->receive(buf, sz); 00266 if (0 == n) { 00267 return CYASSL_CBIO_ERR_WANT_READ; 00268 } else if (n > 0) { 00269 return n; 00270 } else { 00271 return CYASSL_CBIO_ERR_GENERAL; 00272 } 00273 } 00274 00275 int TlsMQTTClient::ioSend(CYASSL* ssl, char *buf, int sz, void *ctx) { 00276 TlsMQTTClient* thiz = (TlsMQTTClient*) ctx; 00277 int n = thiz->tcp->send(buf, sz); 00278 if (0 == n) { 00279 return CYASSL_CBIO_ERR_WANT_WRITE; 00280 } else if (n > 0) { 00281 return n; 00282 } else { 00283 return CYASSL_CBIO_ERR_GENERAL; 00284 } 00285 }
Generated on Tue Jul 12 2022 21:09:00 by 1.7.2