Official reference client implementation for Cumulocity SmartREST on u-blox C027.
Dependencies: C027_Support C12832 LM75B MMA7660 MbedSmartRest mbed-rtos mbed
Fork of MbedSmartRestMain by
Revision 106:c61f0d62b625, committed 2015-05-11
- Comitter:
- xinlei
- Date:
- Mon May 11 18:10:44 2015 +0000
- Parent:
- 105:fd3571349e5d
- Child:
- 107:fc5f25f0e0d5
- Commit message:
- SmartRestSSLSocket and various bug-fixes for rc3
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CyaSSL.lib Mon May 11 18:10:44 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/wolfSSL/code/CyaSSL/#1d1b8be1715f
--- a/MbedAgent.cpp Fri May 08 14:50:43 2015 +0000 +++ b/MbedAgent.cpp Mon May 11 18:10:44 2015 +0000 @@ -74,8 +74,10 @@ int MbedAgent::run() { // device bootstrapping process - if (!_bootstrap.setUpCredentials()) + if (!_bootstrap.setUpCredentials()) { + LCDDisplay::inst().setLines("Bootstrap error"); return -1; + } setAuth(_bootstrap.username(), _bootstrap.password()); aInfo("Set auth: %s:%s (%s)\n", srUsername, srPassword, srAuthStr); @@ -83,6 +85,7 @@ LCDDisplay::inst().setLines("Connect to Cloud", srHost); if (!_integration.integrate()) { + LCDDisplay::inst().setLines("Integrate failure"); return -2; } setX_ID(_client.getIdentifier()); @@ -102,8 +105,8 @@ wdt.kick(60.0); // set a 60.0 seconds watchdog while (true) { for (size_t i = 0; i < N; ++i) { -// if (reporters[i] == &conf) { - size_t l = reporters[i]->read(buf2, SMARRESTBODY_SIZE, status, DISPLAY_LEN); +// if (reporters[i] == &acc) { + size_t l = reporters[i]->read(buf2, sizeof(buf2), status, DISPLAY_LEN); bool b = l; if (b) { // Refresh LCD display needed LCDDisplay::inst().setThirdLine(status); @@ -112,10 +115,10 @@ } lcdThirdLineBlank = !b; if (b) { - int l2 = snprintf(buf, SMARTREST_SIZE, fmtSmartRest, "/s", l, buf2); + int l2 = snprintf(buf, sizeof(buf), fmtSmartRest, "/s", l, buf2); l2 = sock.sendOnly(buf, l2); if (l2 < 0) - aError(status); + aWarning("%s\n", status); } // } }
--- a/MbedAgent.h Fri May 08 14:50:43 2015 +0000 +++ b/MbedAgent.h Mon May 11 18:10:44 2015 +0000 @@ -44,7 +44,7 @@ Acceleration acc; ConfigSync conf; char buf[SMARTREST_SIZE]; - char buf2[SMARRESTBODY_SIZE]; + char buf2[SMARTREST_BODY_SIZE]; char status[DISPLAY_LEN]; AbstractReporter *reporters[N]; SmartRestSocket sock;
--- a/config/ConfigParser.cpp Fri May 08 14:50:43 2015 +0000 +++ b/config/ConfigParser.cpp Mon May 11 18:10:44 2015 +0000 @@ -40,16 +40,11 @@ void ConfigParser::parseValue(Token& tok) { if (tok.type != Token::NONE) { - if (strncmp(key, "interval", MAX_KEY_LEN) == 0 && - tok.type != Token::INT) { - parseError(tok); - } else { - memset(value, 0, MAX_VALUE_LEN); - size_t num = tok.len<MAX_VALUE_LEN ? tok.len : MAX_VALUE_LEN; - strncpy(value, tok.p, num); - dict.set(key, value); - ptrPF = &ConfigParser::parseSemiColon; - } + memset(value, 0, MAX_VALUE_LEN); + size_t num = tok.len<MAX_VALUE_LEN ? tok.len : MAX_VALUE_LEN; + strncpy(value, tok.p, num); + dict.set(key, value); + ptrPF = &ConfigParser::parseSemiColon; } else { parseError(tok); }
--- a/config/ConfigSync.cpp Fri May 08 14:50:43 2015 +0000 +++ b/config/ConfigSync.cpp Mon May 11 18:10:44 2015 +0000 @@ -10,12 +10,21 @@ bool validateConfiguration(Dict& d) { - return d.get(INTERVAL_KEY); + const Dict::Item *p = d.get(INTERVAL_KEY); + if (p) { + int v = 0, n = 0; + sscanf(p->value, "%d%n", &v, &n); + if (v > 0 && n == strlen(p->value)) + return true; + else + return false; + } else + return false; } size_t ConfigSync::read(char *buf, size_t maxLen, char *status, size_t num) { - static const char *fmt = "130,%ld,%s,%.*s\r\n"; + static const char *fmt = "130,%ld,\"%s\",%.*s\r\n"; int l = 0; if (changed) { changed = false;
--- a/main.cpp Fri May 08 14:50:43 2015 +0000 +++ b/main.cpp Mon May 11 18:10:44 2015 +0000 @@ -4,6 +4,7 @@ #include "rtos.h" #include "MDM.h" #include "GPS.h" +#include "cyassl/ssl.h" #include "DeviceInfo.h" #include "Storage.h" @@ -23,10 +24,11 @@ //#define SIM_APN "" //#define SIM_USER "" //#define SIM_PASS "" -//MDMRtos<MDMSerial> *pMdm; -MDMSerial* pMdm; -unsigned short getMNCLen(const char *imsi) +MDMSerial* pMdm = NULL; +//CYASSL_CTX *pCtx = NULL; + +static unsigned short getMNCLen(const char *imsi) { if (strncmp(imsi, "310", 3) != 0) // Non American ISMI return 2; @@ -34,22 +36,53 @@ return 3; } -void enableDebug() +static void enableDebug() { setLevel(A_DEBUG); if (pMdm) pMdm->setDebug(3); } -void disableDebug() +static void disableDebug() { setLevel(A_NONE); if (pMdm) pMdm->setDebug(-1); } +static void shutdown() +{ +// CyaSSL_CTX_free(pCtx); +// CyaSSL_Cleanup(); + pMdm->disconnect(); + pMdm->powerOff(); +} + +//static int send(CYASSL *ssl, char *buf, int size, void* ctx) +//{ +// int sockfd = *(int*)ctx; +// int ret = pMdm->socketSend(sockfd, buf, size); +// printf("[send](%d, %p): %d/%d\n", sockfd, ssl, ret, size); +// if (ret >= 0) +// return ret; +// else +// return CYASSL_CBIO_ERR_GENERAL; +//} +// +//static int recv(CYASSL *ssl, char *buf, int maxSize, void* ctx) +//{ +// int sockfd = *(int*)ctx; +// int ret = pMdm->socketRecv(sockfd, buf, maxSize); +// printf("[recv](%d, %p): %d/%d\n", sockfd, ssl, ret, maxSize); +// if (ret >= 0) +// return ret; +// else +// return CYASSL_CBIO_ERR_GENERAL; +//} + int main() { + LCDDisplay::inst().setLines("Mbed Agent V2.1rc3", srHost); set_time(1256729737); MDMRtos<MDMSerial> mdm; pMdm = &mdm; @@ -58,13 +91,23 @@ joystickUp.rise(&enableDebug); joystickDown.rise(&disableDebug); +// CyaSSL_Init(); +// pCtx = CyaSSL_CTX_new(CyaTLSv1_2_client_method()); +// CyaSSL_Debugging_ON(); +// if (pCtx == NULL) { +// shutdown(); +// return 1; +// } +// CyaSSL_CTX_set_verify(pCtx, SSL_VERIFY_NONE, 0); +// CyaSSL_CTX_set_cipher_list(pCtx, "DHE-RSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA"); +// CyaSSL_SetIORecv(pCtx, recv); +// CyaSSL_SetIOSend(pCtx, send); + MDMParser::DevStatus devStatus; - LCDDisplay::inst().setLines("Mbed Agent V2.1rc3", srHost); if (!mdm.init(SIM_PIN, &devStatus)) { LCDDisplay::inst().setLines("Modem Init Failure", "No SIM card found", "Or SIM has PIN"); - mdm.disconnect(); - mdm.powerOff(); - return 1; + shutdown(); + return 2; } DigitalIn fireButton(D4); @@ -75,16 +118,14 @@ LCDDisplay::inst().setLines("Reset Failure"); } Thread::wait(2000); - mdm.disconnect(); - mdm.powerOff(); + shutdown(); return 0; } aInfo("Main Thread: %p\r\n", Thread::gettid()); LCDDisplay::inst().setLines("Register Network...", "IMEI", devStatus.imei); if (!mdm.registerNet()) { LCDDisplay::inst().setLines("No Network Coverage"); - mdm.disconnect(); - mdm.powerOff(); + shutdown(); return 3; } @@ -100,8 +141,7 @@ snprintf(s, sizeof(s), "%.*s-%.*s", 3, p, getMNCLen(p), p+3); } LCDDisplay::inst().setLines("Wrong APN Settting", "MCC-MNC:", s); - mdm.disconnect(); - mdm.powerOff(); + shutdown(); return 4; } @@ -111,8 +151,7 @@ LCDDisplay::inst().setLines("Agent Init"); if (!agent.init()) { - mdm.disconnect(); - mdm.powerOff(); + shutdown(); return 5; } LCDDisplay::inst().setLines("Agent Run"); @@ -129,14 +168,9 @@ break; } } - - switch (ret) { - case -1: LCDDisplay::inst().setLines("Bootstrap error"); break; - case -2: LCDDisplay::inst().setLines("Integrate failure"); break; - default: agent.loop(); - } - mdm.disconnect(); - mdm.powerOff(); + if (ret == 0) + agent.loop(); + shutdown(); return ret; } }
--- a/operation/ControlParser.cpp Fri May 08 14:50:43 2015 +0000 +++ b/operation/ControlParser.cpp Mon May 11 18:10:44 2015 +0000 @@ -103,7 +103,7 @@ size_t num = tok.len < 30 ? tok.len : 30; if (tok.type == Token::STRING) strncpyEscape(line, tok.p, num); - else + else if (tok.type != Token::NONE) strncpy(line, tok.p, num); LCDDisplay::inst().setFirstLine(line); } else if (opType == 222) {
--- a/operation/PollThread.cpp Fri May 08 14:50:43 2015 +0000 +++ b/operation/PollThread.cpp Mon May 11 18:10:44 2015 +0000 @@ -6,10 +6,10 @@ bool PollThread::handshake() { - int l = snprintf(buf2, SMARRESTBODY_SIZE, "%s", "80\r\n"); - l = snprintf(buf, SMARTREST_SIZE, fmtSmartRest, uri, l, buf2); - sock.set_blocking(false); - l = sock.sendAndReceive(buf, l, SMARTREST_SIZE); + int l = snprintf(buf2, sizeof(buf2), "%s", "80\r\n"); + l = snprintf(buf, sizeof(buf), fmtSmartRest, uri, l, buf2); + sock.setBlocking(3000); + l = sock.sendAndReceive(buf, l, sizeof(buf)); if (l < 0) return false; size_t i = 0; @@ -22,19 +22,19 @@ bool PollThread::subscribe() { - int l = snprintf(buf2, SMARRESTBODY_SIZE, "81,%s,%s\r\n", bayeuxId, chn); - l = snprintf(buf, SMARTREST_SIZE, fmtSmartRest, uri, l, buf2); - sock.set_blocking(false); + int l = snprintf(buf2, sizeof(buf2), "81,%s,%s\r\n", bayeuxId, chn); + l = snprintf(buf, sizeof(buf), fmtSmartRest, uri, l, buf2); + sock.setBlocking(3000); l = sock.sendOnly(buf, l); return l>=0; } bool PollThread::connect() { - int l = snprintf(buf2, SMARRESTBODY_SIZE, "83,%s\r\n", bayeuxId); - l = snprintf(buf, SMARTREST_SIZE, fmtSmartRest, uri, l, buf2); - sock.set_blocking(true); - l = sock.sendAndReceive(buf, l, SMARTREST_SIZE); + int l = snprintf(buf2, sizeof(buf2), "83,%s\r\n", bayeuxId); + l = snprintf(buf, sizeof(buf), fmtSmartRest, uri, l, buf2); + sock.setBlocking(-1); + l = sock.sendAndReceive(buf, l, sizeof(buf)); return l>=0; }
--- a/operation/PollThread.h Fri May 08 14:50:43 2015 +0000 +++ b/operation/PollThread.h Mon May 11 18:10:44 2015 +0000 @@ -13,7 +13,6 @@ sock(), parser(pool, configSync), thread(PollThread::threadWrapper, this) { strncpy(uri, "/devicecontrol/notifications", sizeof(uri)); - sock.set_blocking(true); } virtual ~PollThread() {} bool handshake(); @@ -27,7 +26,7 @@ char uri[30]; char bayeuxId[50]; char buf[SMARTREST_SIZE]; - char buf2[SMARRESTBODY_SIZE]; + char buf2[SMARTREST_BODY_SIZE]; SmartRestSocket sock; ControlParser parser; Thread thread;
--- a/operation/ReportThread.cpp Fri May 08 14:50:43 2015 +0000 +++ b/operation/ReportThread.cpp Mon May 11 18:10:44 2015 +0000 @@ -1,11 +1,11 @@ #include "ReportThread.h" #include "logging.h" -const char *fmt2 = "111,%ld,%s\r\n"; +static const char *fmt2 = "111,%ld,%s\r\n"; void ReportThread::threadFunc() { - sock.set_blocking(false); + sock.setBlocking(3000); while (true) { osEvent e = ipool.get(); if (e.status == osEventMail) { @@ -21,7 +21,7 @@ id = op->identifier; OperationState state = op->state; ipool.free(op); - l += snprintf(buf2+l, SMARRESTBODY_SIZE-l, fmt2, id, strOperationState(state)); + l += snprintf(buf2+l, sizeof(buf2)-l, fmt2, id, strOperationState(state)); } else { break; }
--- a/operation/ReportThread.h Fri May 08 14:50:43 2015 +0000 +++ b/operation/ReportThread.h Mon May 11 18:10:44 2015 +0000 @@ -18,7 +18,7 @@ char uri[4]; OperationPool& ipool; char buf[SMARTREST_SIZE]; - char buf2[SMARRESTBODY_SIZE]; + char buf2[SMARTREST_BODY_SIZE]; SmartRestSocket sock; Thread thread; };
--- a/util/SmartRestConf.cpp Fri May 08 14:50:43 2015 +0000 +++ b/util/SmartRestConf.cpp Mon May 11 18:10:44 2015 +0000 @@ -9,11 +9,10 @@ const char *srX_ID = "com_cumulocity_MbedAgent_1.5.2"; const char *srHost = "developer.cumulocity.com"; //const char *srHost = "management.m2m-devicecloud.com"; -const int srPort = 80; long deviceID = 0; char fmtSmartRest[200] = {0}; -void setAuthStr(const char* p1, const char* p2) +static void setAuthStr(const char* p1, const char* p2) { memset(srAuthStr, 0, sizeof(srAuthStr)); size_t ul = strlen(p1); @@ -38,17 +37,17 @@ } } -void setUsername(const char* username) +static void setUsername(const char* username) { srUsername = username; } -void setPassword(const char* password) +static void setPassword(const char* password) { srPassword = password; } -void setSmartRestFmt() +static void setSmartRestFmt() { const char fmt[] = "POST %%s HTTP/1.0\r\nHost: %s\r\nAuthorization: Basic %s\r\nX-Id: %s\r\nContent-Length: %%d\r\n\r\n%%s"; snprintf(fmtSmartRest, sizeof(fmtSmartRest), fmt, srHost, srAuthStr, srX_ID);
--- a/util/SmartRestConf.h Fri May 08 14:50:43 2015 +0000 +++ b/util/SmartRestConf.h Mon May 11 18:10:44 2015 +0000 @@ -1,16 +1,19 @@ #ifndef SMARTRESTCONF_H #define SMARTRESTCONF_H #define SMARTREST_SIZE 600 -#define SMARRESTBODY_SIZE 300 +#define SMARTREST_BODY_SIZE 350 +#define SMARTREST_SSL_SIZE 6000 +#define SMARTREST_SSL_BODY_SIZE 5000 extern const char *srUsername; extern const char *srPassword; extern char srAuthStr[]; extern const char *srX_ID; extern const char *srHost; -extern const int srPort; extern long deviceID; extern char fmtSmartRest[]; +const int srPort = 80; +const int srSSLPort = 443; void setDeviceID(long id); void setAuth(const char* username, const char* password);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/SmartRestSSLSocket.cpp Mon May 11 18:10:44 2015 +0000 @@ -0,0 +1,95 @@ +#include <string.h> +#include "MDM.h" +#include "SmartRestSSLSocket.h" +#include "SmartRestConf.h" +#include "logging.h" + +char SmartRestSSLSocket::cachedIP[16] = {0}; + +int SmartRestSSLSocket::connect() +{ + sockfd = pMdm->socketSocket(MDMParser::IPPROTO_TCP); + if (sockfd < 0) + return -1; + bool n = false; + ipLock.lock(); + for (size_t i = 0; i < 3; ++i) { + if (cachedIP[0] == 0) { + MDMParser::IP ip = pMdm->gethostbyname(srHost); + if (ip == NOIP) continue; + const unsigned char *c = (const unsigned char*)&ip; + snprintf(cachedIP, sizeof(cachedIP), "%u.%u.%u.%u", + c[3], c[2], c[1], c[0]); + } + n = pMdm->socketConnect(sockfd, cachedIP, srSSLPort); + if (n) { + pMdm->socketSetBlocking(sockfd, timeout); + CyaSSL_set_fd(ssl, sockfd); + break; + } else { + cachedIP[0] = 0; + } + } + ipLock.unlock(); + return n ? 0 : -1; +} + +int SmartRestSSLSocket::close() +{ + if (ssl) + CyaSSL_shutdown(ssl); + bool ret = true; + if (sockfd >= 0) + pMdm->socketFree(sockfd); +// ret = pMdm->socketClose(sockfd); + sockfd = -1; + return ret ? 0 : -1; +} + +int SmartRestSSLSocket::sendOnly(char *buf, int size) +{ + int l = connect(); + if (l < 0) { + aError("%s\n", "SO: connect"); + return -3; + } + l = CyaSSL_write(ssl, buf, size); + close(); + if (l < 0) { + char errorString[80]; + int err = CyaSSL_get_error(ssl, 0); + CyaSSL_ERR_error_string(err, errorString); + aError("SO: %s\n", errorString); + return -2; + } else { + return l; + } +} + +int SmartRestSSLSocket::sendAndReceive(char *buf, int size, int maxSize) +{ + int l = connect(); + if (l < 0) + return -3; + l = CyaSSL_write(ssl, buf, size); + if (l < 0) { + char errorString[80]; + int err = CyaSSL_get_error(ssl, 0); + CyaSSL_ERR_error_string(err, errorString); + aError("S: %s\n", errorString); + close(); + return -2; + } else { + l = CyaSSL_read(ssl, buf, maxSize); + if (l >= 0) + buf[l] = 0; + else { + char errorString[80]; + int err = CyaSSL_get_error(ssl, 0); + CyaSSL_ERR_error_string(err, errorString); + printf("R: %s\n", errorString); + } + close(); + return l; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/SmartRestSSLSocket.h Mon May 11 18:10:44 2015 +0000 @@ -0,0 +1,40 @@ +#ifndef SMARTRESTSSLSOCKET_H +#define SMARTRESTSSLSOCKET_H +#include "mbed.h" +#include "rtos.h" +#include "MDM.h" +#include "cyassl/ssl.h" + +extern MDMSerial *pMdm; +extern CYASSL_CTX *pCtx; + +class SmartRestSSLSocket +{ +public: + SmartRestSSLSocket(): timeout(3000), sockfd(-1), ssl(NULL) { +// sockfd = pMdm->socketSocket(MDMParser::IPPROTO_TCP); + ssl = CyaSSL_new(pCtx); + } + virtual ~SmartRestSSLSocket() { + close(); +// pMdm->socketFree(sockfd); + CyaSSL_free(ssl); + } + int sendOnly(char *buf, int size); + int sendAndReceive(char *buf, int size, int maxSize); + void setBlocking(int _timeout = -1) { + // timeout in milliseconds + timeout = _timeout; + } +protected: + int connect(); + int close(); +private: + static char cachedIP[16]; + int timeout; + int sockfd; + CYASSL *ssl; + Mutex ipLock; +}; + +#endif /* SMARTRESTSSLSOCKET_H */ \ No newline at end of file
--- a/util/SmartRestSocket.cpp Fri May 08 14:50:43 2015 +0000 +++ b/util/SmartRestSocket.cpp Mon May 11 18:10:44 2015 +0000 @@ -2,7 +2,6 @@ #include "SmartRestSocket.h" #include "SmartRestConf.h" -//memset((void*)SmartRestSocket::cachedIP, 0, sizeof(SmartRestSocket::cachedIP)); char SmartRestSocket::cachedIP[16] = {0}; int SmartRestSocket::connect() @@ -20,6 +19,10 @@ } n = TCPSocketConnection::connect(cachedIP, srPort); if (n >= 0) { + if (timeout == -1) + Socket::set_blocking(true); + else + Socket::set_blocking(false, timeout); break; } else { cachedIP[0] = '\0';
--- a/util/SmartRestSocket.h Fri May 08 14:50:43 2015 +0000 +++ b/util/SmartRestSocket.h Mon May 11 18:10:44 2015 +0000 @@ -6,16 +6,17 @@ class SmartRestSocket : private TCPSocketConnection { public: - SmartRestSocket(): TCPSocketConnection() {} + SmartRestSocket(): TCPSocketConnection(), timeout(-1) {} virtual ~SmartRestSocket() {} int sendOnly(char *buf, int size); int sendAndReceive(char *buf, int size, int maxSize); - void set_blocking(bool blocking, unsigned int timeout = 3000) { // timeout in milliseconds - Socket::set_blocking(blocking, timeout); + void setBlocking(int _timeout = -1) { // timeout in milliseconds + timeout = _timeout; } private: int connect(); static char cachedIP[16]; + int timeout; Mutex ipLock; };