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.

MQTTNetwork.h

Committer:
lokeshhk
Date:
2017-05-30
Revision:
6:5f037f24ce29
Parent:
5:ea9f483e0294

File content as of revision 6:5f037f24ce29:

/*******************************************************************************
 * Copyright (c) 2017 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 *
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *    Lokesh K Haralakatta  Initial implementation to support mbed OS 5
 *    Lokesh K Haralakatta  Added SSL/TLS Support
 *******************************************************************************/
#ifndef MQTTNetwork_H
#define MQTTNetwork_H

// Network related header files
#include "NetworkInterface.h"
#include "EthernetInterface.h"

// mbedTLS related header files
#include "mbedtls/platform.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"

//Include certificates header
#include "Certificates.h"

namespace IoTF {

     //Class to represent Network layer
     class MQTTNetwork {
         private:
             //Pointer member for ethernet interface
             NetworkInterface* network;

             //Pointer member to represent socket
             TCPSocket* socket;

             //Variable to stored server port
             int serverPort;

             //Poniter mebers for mbedTLS structures
             mbedtls_entropy_context* _entropy;
             mbedtls_ctr_drbg_context* _ctr_drbg;
             mbedtls_x509_crt* _cacert;
             mbedtls_ssl_context* _ssl;
             mbedtls_ssl_config* _ssl_conf;
         public:
             //Default constructor to initialize network, mbedTLS structures
             MQTTNetwork(): serverPort(1883){
                 //Instantiate new ethernet interface
                 network = new EthernetInterface();
                 //Connect to ethernet interface
                 network->connect();
                 //Create socket with created ethernet interface
                 socket = new TCPSocket(network);

                 //Instantiate mbedTLS structures
                 _entropy = new mbedtls_entropy_context();
                 _ctr_drbg = new mbedtls_ctr_drbg_context();
                 _cacert = new mbedtls_x509_crt();
                 _ssl = new mbedtls_ssl_context();
                 _ssl_conf = new mbedtls_ssl_config();

                 //Initialize mbedTLS structures
                 mbedtls_entropy_init(_entropy);
                 mbedtls_ctr_drbg_init(_ctr_drbg);
                 mbedtls_x509_crt_init(_cacert);
                 mbedtls_ssl_init(_ssl);
                 mbedtls_ssl_config_init(_ssl_conf);
             }

             //Getter method to return underlying EthernetInterface
             NetworkInterface* getEth()
             {
                 return network;
             }

             //Destructor to release the resources
             ~MQTTNetwork() {
                 //Release mbedTLS resources
                 mbedtls_entropy_free(_entropy);
                 mbedtls_ctr_drbg_free(_ctr_drbg);
                 mbedtls_x509_crt_free(_cacert);
                 mbedtls_ssl_free(_ssl);
                 mbedtls_ssl_config_free(_ssl_conf);

                 //Free the allocated memory for socket and network pointers
                 delete socket;
                 delete network;

                 //Free the allocated memory for mbedTLS structures
                 delete _entropy;
                 delete _ctr_drbg;
                 delete _cacert;
                 delete _ssl;
                 delete _ssl_conf;
             }

             //Connect method to establish TCP socket connection
             //If port=1883, opens unsecured socket connection
             //If port is other than 1883, opens secured socket connection
             int connect(const char*host, int port){
                int rc = -1;

                serverPort = port;
                if(port == 1883)
                     //Establish unsecured socket connection
                     rc = socket->connect(host, port);
                else{
                        //Establish secure socket connection using SSL/TLS
                        //Perform mbedTLS initialization
                        if((rc = initializeTLS(host)) == 0){
                           if((rc = socket->connect(host, port))==0){
                             printf("Socket connection to %s:%d successful...\r\n",host,port);
                             //Perform SSL handshake
                             if ((rc = mbedtls_ssl_handshake(_ssl)) < 0) {
                                     if (rc != MBEDTLS_ERR_SSL_WANT_READ &&
                                             rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
                                     printf("mbedtls_ssl_handshake failed - 0x%x\r\n", -rc);
                                     }
                                    goto exit;
                             }
                           }
                        }
                }

                exit:
                        return rc;
             }

             //Method to initialize mbedTLS structures
             int initializeTLS(const char* hostName){
                     int rc = 0;

                     //Initialize entropy seeding
                     if ((rc = mbedtls_ctr_drbg_seed(_ctr_drbg, mbedtls_entropy_func, _entropy,
                                       (const unsigned char *) tlsClientName,
                                       sizeof (tlsClientName))) != 0) {
                         printf("mbedtls_crt_drbg_init failed - 0x%x\r\n", -rc);
                         goto exit;
                     }

                     //Parse certificates into mbedTLS structure
                     if ((rc = mbedtls_x509_crt_parse(_cacert, (const unsigned char *) serverCert,
                                        sizeof(serverCert))) != 0) {
                         printf("mbedtls_x509_crt_parse for serverCert failed - 0x%x\r\n", -rc);
                         goto exit;
                     }

                     //Set ssl config details
                     if ((rc = mbedtls_ssl_config_defaults(_ssl_conf,
                                     MBEDTLS_SSL_IS_CLIENT,
                                     MBEDTLS_SSL_TRANSPORT_STREAM,
                                     MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
                         printf("mbedtls_ssl_config_defaults failed - 0x%x\r\n", -rc);
                         goto exit;
                     }

                     //Add parsed server certificate to ssl config
                     mbedtls_ssl_conf_ca_chain(_ssl_conf, _cacert, NULL);

                     mbedtls_ssl_conf_rng(_ssl_conf, mbedtls_ctr_drbg_random, _ctr_drbg);

                     //Set Server Certificate authorization mode
                     mbedtls_ssl_conf_authmode(_ssl_conf, MBEDTLS_SSL_VERIFY_NONE);

                     //Perform mbedTLS ssl setup
                     if ((rc = mbedtls_ssl_setup(_ssl, _ssl_conf)) != 0) {
                         printf("mbedtls_ssl_setup failed - 0x%x\r\n", -rc);
                         goto exit;
                     }

                     //Set hostname to establish SSL connection
                     mbedtls_ssl_set_hostname(_ssl, hostName);

                     //Set buffer I/O methods for SSL connection
                     mbedtls_ssl_set_bio(_ssl, static_cast<void *>(socket),
                                                tlsWrite, tlsRead, NULL );

               exit:
                     return rc;
             }

             //Method to read from SSL socket
             static int tlsRead(void *ctx,unsigned char* buffer, size_t len) {
                 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
                 int rc = socket->recv(buffer, len);
                 return rc;
             }

             //Method to write to SSL socket
             static int tlsWrite(void *ctx,const unsigned char* buffer, size_t len) {
                 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
                 int rc = socket->send(buffer, len);
                 return rc;
             }

             //Method to read MQTT Packets
             int read(unsigned char* buffer, int len, int timeout) {
                 int rc = 0;

                 if(serverPort == 1883)
                     rc = socket->recv(buffer,len);
                 else
                     rc = mbedtls_ssl_read(_ssl, (unsigned char *) buffer, len);

                 return rc;
             }

             //Method to send MQTT Packets
             int write(unsigned char* buffer, int len, int timeout) {
                 int rc = 0;

                 if(serverPort == 1883)
                     rc = socket->send(buffer,len);
                 else
                     rc = mbedtls_ssl_write(_ssl, (const unsigned char *) buffer, len);

                 return rc;
             }

             //Method to close socket connection
             void disconnect(){
                 socket->close();
             }

     };
}
#endif