Had to fork with a different name, because of some incompatibility issues.

Dependencies:   MQTT

MQTTNetwork.h

Committer:
lamell
Date:
2020-09-14
Revision:
29:40cc05c6c14b
Parent:
26:3cfeb898b183

File content as of revision 29:40cc05c6c14b:

/*******************************************************************************
 * 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

//mbed
#include "mbed.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"

#include "Logging.h"

//extern RawSerial pc;

namespace IoTF {

     //Class to represent Network layer
     class MQTTNetwork {
         private:
             //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:
             //Pointer member for ethernet interface
             NetworkInterface *network;
            

            //EthernetInterface network;
            //Create socket with created ethernet interface
            TCPSocket  socket;
            
            //Default constructor to initialize network, mbedTLS structures
             MQTTNetwork(): serverPort(1883){
                 //Instantiate new ethernet interface
                 //network = new EthernetInterface();
                 //Connect to ethernet interface
                 network = NetworkInterface::get_default_instance();
                 nsapi_error_t  neterr = network->connect();

                 if (neterr != NSAPI_ERROR_OK) {
                    debug("Net disconn %d\r\n",network->disconnect());
                    debug("%d\r\n",network->connect());
                 }

                 debug("%d\r\n",socket.open(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 network;
                 //delete socket;

                 //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;

            
                LOG("%d\r\n",socket.open(network));

                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){
                               rc = socket.connect(host, port);
                               //LOG("%d\r\n",rc);
                               if((rc)==0){
                             LOG("Socket connection to %s:%d successful...\r\n",host,port);
                             //Perform SSL handshake
                             rc = mbedtls_ssl_handshake(_ssl);
                             //LOG("%d\r\n",rc);
                             if ((rc) < 0) {
                                     if (rc != MBEDTLS_ERR_SSL_WANT_READ &&
                                             rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
                                     LOG("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;
LOG("initializeTLS(%s)\r\n",hostName);

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

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

                     //Set ssl config details
                     rc = mbedtls_ssl_config_defaults(_ssl_conf,
                                     MBEDTLS_SSL_IS_CLIENT,
                                     MBEDTLS_SSL_TRANSPORT_STREAM,
                                     MBEDTLS_SSL_PRESET_DEFAULT);
                     //LOG("%d\r\n",rc);
                     if ((rc) != 0) {
                         LOG("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);
//LOG("mbedtls_ssl_conf_ca_chain(_ssl_conf, _cacert, NULL)\r\n");
                     mbedtls_ssl_conf_rng(_ssl_conf, mbedtls_ctr_drbg_random, _ctr_drbg);
//LOG("mbedtls_ssl_conf_rng(_ssl_conf, mbedtls_ctr_drbg_random, _ctr_drbg)\r\n");
                     //Set Server Certificate authorization mode
                     mbedtls_ssl_conf_authmode(_ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
//LOG("mbedtls_ssl_conf_authmode(_ssl_conf, MBEDTLS_SSL_VERIFY_NONE)\r\n");
                     //Perform mbedTLS ssl setup
                     rc = mbedtls_ssl_setup(_ssl, _ssl_conf);
                     //LOG("%d\r\n",rc);
                     if ((rc) != 0) {
                         LOG("mbedtls_ssl_setup failed - 0x%x\r\n", -rc);
                         goto exit;
                     }

                     //Set hostname to establish SSL connection
                     mbedtls_ssl_set_hostname(_ssl, hostName);
//LOG("mbedtls_ssl_set_hostname(_ssl, hostName)\r\n");
                     //Set buffer I/O methods for SSL connection
                     mbedtls_ssl_set_bio(_ssl, static_cast<void *>(&socket),
                                                tlsWrite, tlsRead, NULL );
//LOG("mbedtls_ssl_set_bio(_ssl, static_cast<void *>(&socket),tlsWrite, tlsRead, NULL )\r\n");
               exit:
                     LOG("%d\r\n", rc);
                     return rc;
             }

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

             //Method to write to SSL socket
             static int tlsWrite(void *ctx,const unsigned char* buffer, size_t len) {
                 TCPSocket *wrsocket = static_cast<TCPSocket *>(ctx);
                 int rc = wrsocket->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