A library that simplifies interactions with the IBM Internet of Things Foundation

Dependencies:   MQTT

Dependents:   IBMIoTClientLibrarySamplefinal IBMWIoTPSecureClientSample IBMIoTClientLibrarySample

Introduction

Use the mBed C++ client library to easily connect mBed devices, such as LPC1768 or FRDM-K64F, to the IBM Watson™ IoT Platform service.

Although the library uses C++, it still avoids dynamic memory allocations and the use of STL functions, because the mBed devices sometimes have idiosyncratic memory models that make porting difficult. In any case, the library allows you to make memory use as predictable as possible.

Dependencies

DependencyDescription
Eclipse Paho MQTT libraryProvides an MQTT client library for mBed devices. For more information, see Embedded MQTT C/C++ client libraries
mbed-osARM mbed OS

How to use the library

Use the mBed compiler to create your applications when you use the mBed C++ IBMIoTF client library. The mBed compiler provides a lightweight online C/C++ IDE that is configured for writing, compiling, and downloading programs to run on your mBed microcontroller.

Note: You don't have to install or set up anything to get running with mBed.

For information on how to connect an ARM mBed NXP LPC 1768 microcontroller to the Watson IoT Platform, see the mBed C++ client library for IBM Watson IoT Platform recipe.

Supported Features

FeatureSupported?
Device connectivityYes
Event publishYes
Command receiptYes
SSL/TLSYes
Device ManagementNo

License

This library is shipped under License Eclipse Public License - v 1.0 and Eclipse Distribution License v1.0

For more information about the Eclipse Public License - v 1.0, refer this page. Also, for more information about the Eclipse Distribution License v1.0, refer this page.

Contributor License Agreement

Version 1.0.0 January 14, 2014

In order for You (as defined below) to make intellectual property Contributions (as defined below) now or in the future to IBM repositories, You must agree to this Contributor License Agreement ("CLA").

Please read this CLA carefully before accepting its terms. By accepting the CLA, You are agreeing to be bound by its terms. If You submit a Pull Request against this repository You must include in the Pull Request a statement of Your acceptance of this CLA.

As used in this CLA: (i) "You" (or "Your") shall mean the entity that is making this Agreement with IBM; (ii)"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is submitted by You to IBM for inclusion in, or documentation of, any of the IBM repositories; (iii) "Submit" (or "Submitted") means any form of communication sent to IBM (e.g. the content You post in the Issue or submit as part of a Pull Request).

This agreement applies to all Contributions You Submit.

This CLA, and the license(s) associated with the particular IBM repositories You are contributing to, provides a license to Your Contributions to IBM and downstream consumers, but You still own Your Contributions, and except for the licenses provided for in this CLA, You reserve all right, title and interest in Your Contributions.

IBM requires that each Contribution You Submit now or in the future comply with the following four commitments.

1) You will only Submit Contributions where You have authored 100% of the content. 2) You will only Submit Contributions to which You have the necessary rights. This means that if You are employed You have received the necessary permissions from Your employer to make the Contributions. 3) Whatever content You Contribute will be provided under the license(s) associated with the particular IBM repository You are contributing to. 4) You understand and agree that IBM repositories and Your contributions are public, and that a record of the contribution (including all personal information You submit with it) is maintained indefinitely and may be redistributed consistent with the license(s) involved. You will promptly notify the Eclipse Foundation if You become aware of any facts or circumstances that would make these commitments inaccurate in any way. To do so, please create an Issue in the appropriate repository.

Committer:
lokeshhk
Date:
Tue May 30 06:36:04 2017 +0000
Revision:
6:5f037f24ce29
Parent:
5:ea9f483e0294
Added mbed-os and mqtt dependencies for the library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lokeshhk 5:ea9f483e0294 1 /*******************************************************************************
lokeshhk 5:ea9f483e0294 2 * Copyright (c) 2017 IBM Corp.
lokeshhk 5:ea9f483e0294 3 *
lokeshhk 5:ea9f483e0294 4 * All rights reserved. This program and the accompanying materials
lokeshhk 5:ea9f483e0294 5 * are made available under the terms of the Eclipse Public License v1.0
lokeshhk 5:ea9f483e0294 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
lokeshhk 5:ea9f483e0294 7 *
lokeshhk 5:ea9f483e0294 8 * The Eclipse Public License is available at
lokeshhk 5:ea9f483e0294 9 * http://www.eclipse.org/legal/epl-v10.html
lokeshhk 5:ea9f483e0294 10 * and the Eclipse Distribution License is available at
lokeshhk 5:ea9f483e0294 11 * http://www.eclipse.org/org/documents/edl-v10.php.
lokeshhk 5:ea9f483e0294 12 *
lokeshhk 5:ea9f483e0294 13 * Contributors:
lokeshhk 5:ea9f483e0294 14 * Lokesh K Haralakatta Initial implementation to support mbed OS 5
lokeshhk 5:ea9f483e0294 15 * Lokesh K Haralakatta Added SSL/TLS Support
lokeshhk 5:ea9f483e0294 16 *******************************************************************************/
lokeshhk 5:ea9f483e0294 17 #ifndef MQTTNetwork_H
lokeshhk 5:ea9f483e0294 18 #define MQTTNetwork_H
lokeshhk 5:ea9f483e0294 19
lokeshhk 5:ea9f483e0294 20 // Network related header files
lokeshhk 5:ea9f483e0294 21 #include "NetworkInterface.h"
lokeshhk 5:ea9f483e0294 22 #include "EthernetInterface.h"
lokeshhk 5:ea9f483e0294 23
lokeshhk 5:ea9f483e0294 24 // mbedTLS related header files
lokeshhk 5:ea9f483e0294 25 #include "mbedtls/platform.h"
lokeshhk 5:ea9f483e0294 26 #include "mbedtls/ssl.h"
lokeshhk 5:ea9f483e0294 27 #include "mbedtls/entropy.h"
lokeshhk 5:ea9f483e0294 28 #include "mbedtls/ctr_drbg.h"
lokeshhk 5:ea9f483e0294 29 #include "mbedtls/error.h"
lokeshhk 5:ea9f483e0294 30 #include "mbedtls/debug.h"
lokeshhk 5:ea9f483e0294 31
lokeshhk 5:ea9f483e0294 32 //Include certificates header
lokeshhk 5:ea9f483e0294 33 #include "Certificates.h"
lokeshhk 5:ea9f483e0294 34
lokeshhk 5:ea9f483e0294 35 namespace IoTF {
lokeshhk 5:ea9f483e0294 36
lokeshhk 5:ea9f483e0294 37 //Class to represent Network layer
lokeshhk 5:ea9f483e0294 38 class MQTTNetwork {
lokeshhk 5:ea9f483e0294 39 private:
lokeshhk 5:ea9f483e0294 40 //Pointer member for ethernet interface
lokeshhk 5:ea9f483e0294 41 NetworkInterface* network;
lokeshhk 5:ea9f483e0294 42
lokeshhk 5:ea9f483e0294 43 //Pointer member to represent socket
lokeshhk 5:ea9f483e0294 44 TCPSocket* socket;
lokeshhk 5:ea9f483e0294 45
lokeshhk 5:ea9f483e0294 46 //Variable to stored server port
lokeshhk 5:ea9f483e0294 47 int serverPort;
lokeshhk 5:ea9f483e0294 48
lokeshhk 5:ea9f483e0294 49 //Poniter mebers for mbedTLS structures
lokeshhk 5:ea9f483e0294 50 mbedtls_entropy_context* _entropy;
lokeshhk 5:ea9f483e0294 51 mbedtls_ctr_drbg_context* _ctr_drbg;
lokeshhk 5:ea9f483e0294 52 mbedtls_x509_crt* _cacert;
lokeshhk 5:ea9f483e0294 53 mbedtls_ssl_context* _ssl;
lokeshhk 5:ea9f483e0294 54 mbedtls_ssl_config* _ssl_conf;
lokeshhk 5:ea9f483e0294 55 public:
lokeshhk 5:ea9f483e0294 56 //Default constructor to initialize network, mbedTLS structures
lokeshhk 5:ea9f483e0294 57 MQTTNetwork(): serverPort(1883){
lokeshhk 5:ea9f483e0294 58 //Instantiate new ethernet interface
lokeshhk 5:ea9f483e0294 59 network = new EthernetInterface();
lokeshhk 5:ea9f483e0294 60 //Connect to ethernet interface
lokeshhk 5:ea9f483e0294 61 network->connect();
lokeshhk 5:ea9f483e0294 62 //Create socket with created ethernet interface
lokeshhk 5:ea9f483e0294 63 socket = new TCPSocket(network);
lokeshhk 5:ea9f483e0294 64
lokeshhk 5:ea9f483e0294 65 //Instantiate mbedTLS structures
lokeshhk 5:ea9f483e0294 66 _entropy = new mbedtls_entropy_context();
lokeshhk 5:ea9f483e0294 67 _ctr_drbg = new mbedtls_ctr_drbg_context();
lokeshhk 5:ea9f483e0294 68 _cacert = new mbedtls_x509_crt();
lokeshhk 5:ea9f483e0294 69 _ssl = new mbedtls_ssl_context();
lokeshhk 5:ea9f483e0294 70 _ssl_conf = new mbedtls_ssl_config();
lokeshhk 5:ea9f483e0294 71
lokeshhk 5:ea9f483e0294 72 //Initialize mbedTLS structures
lokeshhk 5:ea9f483e0294 73 mbedtls_entropy_init(_entropy);
lokeshhk 5:ea9f483e0294 74 mbedtls_ctr_drbg_init(_ctr_drbg);
lokeshhk 5:ea9f483e0294 75 mbedtls_x509_crt_init(_cacert);
lokeshhk 5:ea9f483e0294 76 mbedtls_ssl_init(_ssl);
lokeshhk 5:ea9f483e0294 77 mbedtls_ssl_config_init(_ssl_conf);
lokeshhk 5:ea9f483e0294 78 }
lokeshhk 5:ea9f483e0294 79
lokeshhk 5:ea9f483e0294 80 //Getter method to return underlying EthernetInterface
lokeshhk 5:ea9f483e0294 81 NetworkInterface* getEth()
lokeshhk 5:ea9f483e0294 82 {
lokeshhk 5:ea9f483e0294 83 return network;
lokeshhk 5:ea9f483e0294 84 }
lokeshhk 5:ea9f483e0294 85
lokeshhk 5:ea9f483e0294 86 //Destructor to release the resources
lokeshhk 5:ea9f483e0294 87 ~MQTTNetwork() {
lokeshhk 5:ea9f483e0294 88 //Release mbedTLS resources
lokeshhk 5:ea9f483e0294 89 mbedtls_entropy_free(_entropy);
lokeshhk 5:ea9f483e0294 90 mbedtls_ctr_drbg_free(_ctr_drbg);
lokeshhk 5:ea9f483e0294 91 mbedtls_x509_crt_free(_cacert);
lokeshhk 5:ea9f483e0294 92 mbedtls_ssl_free(_ssl);
lokeshhk 5:ea9f483e0294 93 mbedtls_ssl_config_free(_ssl_conf);
lokeshhk 5:ea9f483e0294 94
lokeshhk 5:ea9f483e0294 95 //Free the allocated memory for socket and network pointers
lokeshhk 5:ea9f483e0294 96 delete socket;
lokeshhk 5:ea9f483e0294 97 delete network;
lokeshhk 5:ea9f483e0294 98
lokeshhk 5:ea9f483e0294 99 //Free the allocated memory for mbedTLS structures
lokeshhk 5:ea9f483e0294 100 delete _entropy;
lokeshhk 5:ea9f483e0294 101 delete _ctr_drbg;
lokeshhk 5:ea9f483e0294 102 delete _cacert;
lokeshhk 5:ea9f483e0294 103 delete _ssl;
lokeshhk 5:ea9f483e0294 104 delete _ssl_conf;
lokeshhk 5:ea9f483e0294 105 }
lokeshhk 5:ea9f483e0294 106
lokeshhk 5:ea9f483e0294 107 //Connect method to establish TCP socket connection
lokeshhk 5:ea9f483e0294 108 //If port=1883, opens unsecured socket connection
lokeshhk 5:ea9f483e0294 109 //If port is other than 1883, opens secured socket connection
lokeshhk 5:ea9f483e0294 110 int connect(const char*host, int port){
lokeshhk 5:ea9f483e0294 111 int rc = -1;
lokeshhk 5:ea9f483e0294 112
lokeshhk 5:ea9f483e0294 113 serverPort = port;
lokeshhk 5:ea9f483e0294 114 if(port == 1883)
lokeshhk 5:ea9f483e0294 115 //Establish unsecured socket connection
lokeshhk 5:ea9f483e0294 116 rc = socket->connect(host, port);
lokeshhk 5:ea9f483e0294 117 else{
lokeshhk 5:ea9f483e0294 118 //Establish secure socket connection using SSL/TLS
lokeshhk 5:ea9f483e0294 119 //Perform mbedTLS initialization
lokeshhk 5:ea9f483e0294 120 if((rc = initializeTLS(host)) == 0){
lokeshhk 5:ea9f483e0294 121 if((rc = socket->connect(host, port))==0){
lokeshhk 5:ea9f483e0294 122 printf("Socket connection to %s:%d successful...\r\n",host,port);
lokeshhk 5:ea9f483e0294 123 //Perform SSL handshake
lokeshhk 5:ea9f483e0294 124 if ((rc = mbedtls_ssl_handshake(_ssl)) < 0) {
lokeshhk 5:ea9f483e0294 125 if (rc != MBEDTLS_ERR_SSL_WANT_READ &&
lokeshhk 5:ea9f483e0294 126 rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
lokeshhk 5:ea9f483e0294 127 printf("mbedtls_ssl_handshake failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 128 }
lokeshhk 5:ea9f483e0294 129 goto exit;
lokeshhk 5:ea9f483e0294 130 }
lokeshhk 5:ea9f483e0294 131 }
lokeshhk 5:ea9f483e0294 132 }
lokeshhk 5:ea9f483e0294 133 }
lokeshhk 5:ea9f483e0294 134
lokeshhk 5:ea9f483e0294 135 exit:
lokeshhk 5:ea9f483e0294 136 return rc;
lokeshhk 5:ea9f483e0294 137 }
lokeshhk 5:ea9f483e0294 138
lokeshhk 5:ea9f483e0294 139 //Method to initialize mbedTLS structures
lokeshhk 5:ea9f483e0294 140 int initializeTLS(const char* hostName){
lokeshhk 5:ea9f483e0294 141 int rc = 0;
lokeshhk 5:ea9f483e0294 142
lokeshhk 5:ea9f483e0294 143 //Initialize entropy seeding
lokeshhk 5:ea9f483e0294 144 if ((rc = mbedtls_ctr_drbg_seed(_ctr_drbg, mbedtls_entropy_func, _entropy,
lokeshhk 5:ea9f483e0294 145 (const unsigned char *) tlsClientName,
lokeshhk 5:ea9f483e0294 146 sizeof (tlsClientName))) != 0) {
lokeshhk 5:ea9f483e0294 147 printf("mbedtls_crt_drbg_init failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 148 goto exit;
lokeshhk 5:ea9f483e0294 149 }
lokeshhk 5:ea9f483e0294 150
lokeshhk 5:ea9f483e0294 151 //Parse certificates into mbedTLS structure
lokeshhk 5:ea9f483e0294 152 if ((rc = mbedtls_x509_crt_parse(_cacert, (const unsigned char *) serverCert,
lokeshhk 5:ea9f483e0294 153 sizeof(serverCert))) != 0) {
lokeshhk 5:ea9f483e0294 154 printf("mbedtls_x509_crt_parse for serverCert failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 155 goto exit;
lokeshhk 5:ea9f483e0294 156 }
lokeshhk 5:ea9f483e0294 157
lokeshhk 5:ea9f483e0294 158 //Set ssl config details
lokeshhk 5:ea9f483e0294 159 if ((rc = mbedtls_ssl_config_defaults(_ssl_conf,
lokeshhk 5:ea9f483e0294 160 MBEDTLS_SSL_IS_CLIENT,
lokeshhk 5:ea9f483e0294 161 MBEDTLS_SSL_TRANSPORT_STREAM,
lokeshhk 5:ea9f483e0294 162 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
lokeshhk 5:ea9f483e0294 163 printf("mbedtls_ssl_config_defaults failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 164 goto exit;
lokeshhk 5:ea9f483e0294 165 }
lokeshhk 5:ea9f483e0294 166
lokeshhk 5:ea9f483e0294 167 //Add parsed server certificate to ssl config
lokeshhk 5:ea9f483e0294 168 mbedtls_ssl_conf_ca_chain(_ssl_conf, _cacert, NULL);
lokeshhk 5:ea9f483e0294 169
lokeshhk 5:ea9f483e0294 170 mbedtls_ssl_conf_rng(_ssl_conf, mbedtls_ctr_drbg_random, _ctr_drbg);
lokeshhk 5:ea9f483e0294 171
lokeshhk 5:ea9f483e0294 172 //Set Server Certificate authorization mode
lokeshhk 5:ea9f483e0294 173 mbedtls_ssl_conf_authmode(_ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
lokeshhk 5:ea9f483e0294 174
lokeshhk 5:ea9f483e0294 175 //Perform mbedTLS ssl setup
lokeshhk 5:ea9f483e0294 176 if ((rc = mbedtls_ssl_setup(_ssl, _ssl_conf)) != 0) {
lokeshhk 5:ea9f483e0294 177 printf("mbedtls_ssl_setup failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 178 goto exit;
lokeshhk 5:ea9f483e0294 179 }
lokeshhk 5:ea9f483e0294 180
lokeshhk 5:ea9f483e0294 181 //Set hostname to establish SSL connection
lokeshhk 5:ea9f483e0294 182 mbedtls_ssl_set_hostname(_ssl, hostName);
lokeshhk 5:ea9f483e0294 183
lokeshhk 5:ea9f483e0294 184 //Set buffer I/O methods for SSL connection
lokeshhk 5:ea9f483e0294 185 mbedtls_ssl_set_bio(_ssl, static_cast<void *>(socket),
lokeshhk 5:ea9f483e0294 186 tlsWrite, tlsRead, NULL );
lokeshhk 5:ea9f483e0294 187
lokeshhk 5:ea9f483e0294 188 exit:
lokeshhk 5:ea9f483e0294 189 return rc;
lokeshhk 5:ea9f483e0294 190 }
lokeshhk 5:ea9f483e0294 191
lokeshhk 5:ea9f483e0294 192 //Method to read from SSL socket
lokeshhk 5:ea9f483e0294 193 static int tlsRead(void *ctx,unsigned char* buffer, size_t len) {
lokeshhk 5:ea9f483e0294 194 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
lokeshhk 5:ea9f483e0294 195 int rc = socket->recv(buffer, len);
lokeshhk 5:ea9f483e0294 196 return rc;
lokeshhk 5:ea9f483e0294 197 }
lokeshhk 5:ea9f483e0294 198
lokeshhk 5:ea9f483e0294 199 //Method to write to SSL socket
lokeshhk 5:ea9f483e0294 200 static int tlsWrite(void *ctx,const unsigned char* buffer, size_t len) {
lokeshhk 5:ea9f483e0294 201 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
lokeshhk 5:ea9f483e0294 202 int rc = socket->send(buffer, len);
lokeshhk 5:ea9f483e0294 203 return rc;
lokeshhk 5:ea9f483e0294 204 }
lokeshhk 5:ea9f483e0294 205
lokeshhk 5:ea9f483e0294 206 //Method to read MQTT Packets
lokeshhk 5:ea9f483e0294 207 int read(unsigned char* buffer, int len, int timeout) {
lokeshhk 5:ea9f483e0294 208 int rc = 0;
lokeshhk 5:ea9f483e0294 209
lokeshhk 5:ea9f483e0294 210 if(serverPort == 1883)
lokeshhk 5:ea9f483e0294 211 rc = socket->recv(buffer,len);
lokeshhk 5:ea9f483e0294 212 else
lokeshhk 5:ea9f483e0294 213 rc = mbedtls_ssl_read(_ssl, (unsigned char *) buffer, len);
lokeshhk 5:ea9f483e0294 214
lokeshhk 5:ea9f483e0294 215 return rc;
lokeshhk 5:ea9f483e0294 216 }
lokeshhk 5:ea9f483e0294 217
lokeshhk 5:ea9f483e0294 218 //Method to send MQTT Packets
lokeshhk 5:ea9f483e0294 219 int write(unsigned char* buffer, int len, int timeout) {
lokeshhk 5:ea9f483e0294 220 int rc = 0;
lokeshhk 5:ea9f483e0294 221
lokeshhk 5:ea9f483e0294 222 if(serverPort == 1883)
lokeshhk 5:ea9f483e0294 223 rc = socket->send(buffer,len);
lokeshhk 5:ea9f483e0294 224 else
lokeshhk 5:ea9f483e0294 225 rc = mbedtls_ssl_write(_ssl, (const unsigned char *) buffer, len);
lokeshhk 5:ea9f483e0294 226
lokeshhk 5:ea9f483e0294 227 return rc;
lokeshhk 5:ea9f483e0294 228 }
lokeshhk 5:ea9f483e0294 229
lokeshhk 5:ea9f483e0294 230 //Method to close socket connection
lokeshhk 5:ea9f483e0294 231 void disconnect(){
lokeshhk 5:ea9f483e0294 232 socket->close();
lokeshhk 5:ea9f483e0294 233 }
lokeshhk 5:ea9f483e0294 234
lokeshhk 5:ea9f483e0294 235 };
lokeshhk 5:ea9f483e0294 236 }
lokeshhk 5:ea9f483e0294 237 #endif