Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SecureDweet.cpp Source File

SecureDweet.cpp

00001 /*
00002  * SecureDweet.h
00003  *
00004  *  Created on: Aug 15, 2016
00005  *      Author: Faheem Inayat
00006  * Created for: Renesas Electronics America HQ, Santa Clara, CA, USA
00007  *
00008  * Copyright (c) 2016 Renesas Electronics America (REA) and Faheem Inayat
00009  */
00010 /*
00011  * MIT License
00012  *
00013  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00014  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00015  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00016  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00017  * furnished to do so, subject to the following conditions:
00018  *
00019  * The above copyright notice and this permission notice shall be included in all copies or
00020  * substantial portions of the Software.
00021  *
00022  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00023  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00024  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00025  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00026  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00027  */
00028 
00029 #include "SecureDweet.h"
00030 #include "Json.h"
00031 
00032 #if 0
00033 //Enable debug
00034     #include <cstdio>
00035     #define logInfo(x, ...) do{std::fprintf(stdout,"%s:%s:%s| [SecureDweet:INFO] "x"\r\n", __FILE__, __func__, __LINE__,##__VA_ARGS__);std::fflush(stdout);}while(0)
00036     #define logWarning(x, ...) do{std::fprintf(stdout,"%s:%s:%s| [SecureDweet:WARN] "x"\r\n", __FILE__, __func__, __LINE__,##__VA_ARGS__);std::fflush(stdout);}while(0)
00037     #define logError(x, ...) do{std::fprintf(stdout,"%s:%s:%s| [SecureDweet:ERROR] "x"\r\n", __FILE__, __func__, __LINE__,##__VA_ARGS__);std::fflush(stdout);}while(0)
00038 #else
00039 //Disable debug
00040     #define logInfo(x, ...)
00041 #endif
00042 
00043 #define logWarning(x, ...)
00044 #define logError(x, ...)
00045 
00046 #define HTTP_BUFFER_SIZE    1024
00047 #define HTTP_CLIENT_DEFAULT_TIMEOUT 300000
00048 
00049 #define DWEET_URL_GET_LATEST "https://dweet.io/get/latest/dweet/for/"
00050 #define DWEET_URL_GET_LISTEN_TO "https://dweet.io/listen/for/dweets/from/"
00051 #define DWEET_KEY_PARAM_NAME "?key="
00052 
00053 const char KEEP_ALIVE_HEADER [] = "Connection: Keep-Alive\r\nKeep-Alive: timeout=300, max=50\r\n";
00054 
00055 SecureDweet::SecureDweet ( IDweetParser * _device, const char * _thingName, const char * _readKey,
00056                            const char * _writeKey )
00057         : device ( _device ), thingName ( _thingName ), readKey ( _readKey ), writeKey ( _writeKey )
00058 {
00059     size_t thingNameLength = strlen ( thingName );
00060     size_t keyLength = 0;
00061 
00062     if ( writeKey != NULL )
00063     {
00064         keyLength = ( strlen ( writeKey ) + strlen ( DWEET_KEY_PARAM_NAME ) );
00065     }
00066     else if ( readKey != NULL )
00067     {
00068         keyLength = ( strlen ( readKey ) + strlen ( DWEET_KEY_PARAM_NAME ) );
00069     }
00070 
00071     {
00072         size_t lastestUrlLength = strlen ( DWEET_URL_GET_LATEST ) + thingNameLength + keyLength;
00073         latestUrl = new char [ lastestUrlLength + 1 ];
00074         int written = sprintf ( latestUrl, "%s%s", DWEET_URL_GET_LATEST, thingName );
00075         if ( writeKey != NULL )
00076         {
00077             sprintf ( latestUrl + written, "%s%s", DWEET_KEY_PARAM_NAME, writeKey );
00078         }
00079         else if ( readKey != NULL )
00080         {
00081             sprintf ( latestUrl + written, "%s%s", DWEET_KEY_PARAM_NAME, readKey );
00082         }
00083     }
00084 
00085     {
00086         size_t listenUrlLength = strlen ( DWEET_URL_GET_LISTEN_TO ) + thingNameLength + keyLength;
00087         listenUrl = new char [ listenUrlLength + 1 ];
00088         int written = sprintf ( listenUrl, "%s%s", DWEET_URL_GET_LISTEN_TO, thingName );
00089         if ( writeKey != NULL )
00090         {
00091             sprintf ( listenUrl + written, "%s%s", DWEET_KEY_PARAM_NAME, writeKey );
00092         }
00093         else if ( readKey != NULL )
00094         {
00095             sprintf ( listenUrl + written, "%s%s", DWEET_KEY_PARAM_NAME, readKey );
00096         }
00097     }
00098 
00099     httpClient = new SecureHttpClient ();
00100     httpClient->setChunkDataListener ( this );
00101     httpRxBuffer = new char[ HTTP_BUFFER_SIZE + 1];
00102     httpText = new HttpText ( httpRxBuffer, HTTP_BUFFER_SIZE );
00103 
00104 //    httpClient -> setPeerVerification ( VERIFY_PEER );
00105 //    // Explicitly set the ROOT certificates for dweet.io
00106 //    if ( httpClient -> addRootCACertificate ( sslCertificates ) != HTTP_OK ){
00107 //        logError ( "loading SSL certificates failed" );
00108 //    }
00109 
00110     listeningFlag = false;
00111 
00112 }
00113 
00114 SecureDweet::SecureDweet ( const SecureDweet & )
00115         : device ( NULL ), thingName ( NULL ), readKey ( NULL ), writeKey ( NULL )
00116 {
00117     latestUrl = NULL;
00118     listenUrl = NULL;
00119     httpClient = NULL;
00120     httpRxBuffer = NULL;
00121     httpText = NULL;
00122     listeningFlag = false;
00123 }
00124 
00125 SecureDweet::~SecureDweet ()
00126 {
00127     delete [] latestUrl;
00128     delete [] listenUrl;
00129     delete httpClient;
00130     delete[] httpRxBuffer;
00131     delete httpText;
00132 }
00133 
00134 void SecureDweet::fetchLatestDweet ()
00135 {
00136     httpClient->setHeader ( NULL );
00137     HttpResult res = httpClient->get ( latestUrl, httpText, HTTP_CLIENT_DEFAULT_TIMEOUT );
00138 
00139     if ( res != HTTP_OK )
00140     {
00141         logError ( "HTTP GET failed [%d][%s]", res, httpRxBuffer );
00142     }
00143     else
00144     {
00145         logInfo ( "Got response:\r\n%s", httpRxBuffer );
00146         device->parseJsonData ( httpRxBuffer );
00147     }
00148 }
00149 
00150 void SecureDweet::chunkRead ( IHttpDataIn * pDataIn )
00151 {
00152     if ( pDataIn != NULL ) {
00153         int chunkDataSize = 0;
00154         int valuesExtracted = sscanf ( httpRxBuffer, "%x", &chunkDataSize );
00155         if ( valuesExtracted == 1 ) // Reading exactly one number
00156         {
00157             // Max Chunk Size is 32-bit (4 Hex Digits).  Parse it!
00158             char hexNumber [ 7 ];
00159             int hexNumberLength = sprintf ( hexNumber, "%X\n\r", chunkDataSize );
00160             char * lastCr = strrchr ( httpRxBuffer + hexNumberLength, '\n' );
00161             if ( lastCr != NULL )
00162             {
00163                 int bufferLength = (int) ( lastCr - ( httpRxBuffer + hexNumberLength ) ) - 1;
00164 
00165                 if ( bufferLength == chunkDataSize ) // There's a possibility that the chunk is complete now.  Try to pass it
00166                 {
00167                     Json::unescape (httpRxBuffer + hexNumberLength);
00168                     logInfo("Got chunked response:\r\n%s", httpRxBuffer + hexNumberLength );
00169                     device->parseJsonData (httpRxBuffer + hexNumberLength );
00170 
00171                     pDataIn -> writeReset();
00172                 }
00173                 else if ( bufferLength > chunkDataSize ) // Something is messed up, just clean up the buffer
00174                 {
00175                     pDataIn -> writeReset();
00176                 }
00177             }
00178         }
00179     }
00180 }
00181 
00182 void SecureDweet::listenToDweet()
00183 {
00184     listeningFlag = true;
00185     while ( listeningFlag == true )
00186     {
00187         httpClient -> setHeader(KEEP_ALIVE_HEADER);
00188         httpClient -> get (listenUrl, httpText, HTTP_CLIENT_DEFAULT_TIMEOUT);
00189         httpClient -> setHeader(NULL);
00190     }
00191 }
00192 
00193 void SecureDweet::stopListentingToDweet ()
00194 {
00195     listeningFlag = false;
00196 }
00197 
00198