A client for the SmartREST protocol from Cumulocity.

Dependencies:   SmartRest

Fork of MbedSmartRest by Vincent Wochnik

Files at this revision

API Documentation at this revision

Comitter:
vwochnik
Date:
Mon Apr 14 11:23:50 2014 +0000
Parent:
13:e76920d5e1ec
Child:
15:0ce90c525e7a
Commit message:
fix

Changed in this revision

HTTPResponseFilter.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPResponseFilter.h Show annotated file Show diff for this revision Revisions of this file
MbedClient.cpp Show annotated file Show diff for this revision Revisions of this file
MbedClient.h Show annotated file Show diff for this revision Revisions of this file
MbedDataSink.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPResponseFilter.cpp	Mon Apr 14 11:23:50 2014 +0000
@@ -0,0 +1,110 @@
+#include "HTTPResponseFilter.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+const char *cExpectedStatus = "HTTP/1.* ";
+
+HTTPResponseFilter::HTTPResponseFilter(AbstractDataSource& source) : _source(source), _state(RESPF_STATE_INIT)
+{
+}
+
+HTTPResponseFilter::~HTTPResponseFilter()
+{
+}
+
+char HTTPResponseFilter::read()
+{
+    if (_state != RESPF_STATE_READ_HEADERS)
+        return 0;
+    return _source.read();
+}
+
+uint8_t HTTPResponseFilter::status()
+{
+    if (_state != RESPF_STATE_READ_HEADERS)
+        return DS_STATUS_ERROR;
+    return _source.status();
+}
+
+uint16_t HTTPResponseFilter::readStatus()
+{
+    uint16_t res = 0; uint8_t state = 0; char c; size_t offset = 0; uint8_t status;
+    
+    if (_state != RESPF_STATE_INIT)
+        return 0;
+
+    while ((state < 3) && (((c = _source.read()) > 0) || ((status = _source.status()) == DS_STATUS_OK))) {
+        switch (state) {
+        case 0: // read expected status line
+            if ((cExpectedStatus[offset] != c) && (cExpectedStatus[offset] != '*'))
+                state = 3;
+            offset++;
+            if (offset == strlen(cExpectedStatus)) {
+                state = 1;
+            }
+            break;
+        case 1:
+            if (isspace(c))
+                state = 2;
+            if (isdigit(c))
+                res = (res * 10) + (c - '0');
+            break;
+        case 2:
+            if (c == '\n')
+                state = 3;
+            break;
+        }
+    }
+
+    if ((status != DS_STATUS_OK) || (state != 3))
+        return 0;
+
+    _state = RESPF_STATE_READ_STATUS;        
+    return res;
+}
+
+bool HTTPResponseFilter::skipHeaders()
+{
+    uint16_t res = 0; uint8_t state = 0; char c; size_t offset = 0; uint8_t status;
+
+    if (_state != RESPF_STATE_READ_STATUS)
+        return false;
+
+    while ((state < 3) && (((c = _source.read()) > 0) || ((status = _source.status()) == DS_STATUS_OK))) {
+        switch (state) {
+        case 0: // start of line
+            if (c == '\r') {
+                if (offset == 0)
+                    state = 2;
+                else
+                    state = 1;
+            } else {
+                offset++;
+            }
+            break;
+        case 1:
+            if (c == '\n') {
+                state = 0;
+                offset = 0;
+            }
+            break;
+        case 2:
+            if (c == '\n')
+                state = 3;
+            break;
+        }
+    }
+
+    if ((status != DS_STATUS_OK) || (state != 3))
+        return false;
+
+    _state = RESPF_STATE_READ_HEADERS;
+    return true;
+}
+
+void HTTPResponseFilter::reset()
+{
+    _state = RESPF_STATE_INIT;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPResponseFilter.h	Mon Apr 14 11:23:50 2014 +0000
@@ -0,0 +1,35 @@
+#ifndef HTTPRESPONSEFILTER_H
+#define HTTPRESPONSEFILTER_H
+
+#include <stddef.h>
+#include "AbstractDataSource.h"
+
+#define RESPF_STATE_INIT 0
+#define RESPF_STATE_READ_STATUS 1
+#define RESPF_STATE_READ_HEADERS 2
+
+/**
+ * Reads and evaluates a HTTP response.
+ * The read() and status() methods allow access to the response content
+ * without HTTP headers.
+ */
+class HTTPResponseFilter : public AbstractDataSource
+{
+public:
+    HTTPResponseFilter(AbstractDataSource& source);
+    ~HTTPResponseFilter();
+    
+    char read();
+    uint8_t status();
+
+    uint16_t readStatus();
+    bool skipHeaders();
+    
+    void reset();
+
+private:
+    AbstractDataSource& _source;
+    uint8_t _state;
+};
+
+#endif
\ No newline at end of file
--- a/MbedClient.cpp	Fri Apr 11 09:33:45 2014 +0000
+++ b/MbedClient.cpp	Mon Apr 14 11:23:50 2014 +0000
@@ -1,14 +1,11 @@
 #include "MbedClient.h"
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include "b64.h"
 #include "mbed.h"
 
-const char *cExpectedStatus = "HTTP/1.* 200 OK";
-
 MbedClient::MbedClient(const char* host, uint16_t port, const char* username, const char* password)
-    : _host(host), _port(port), _username(username), _password(password), _source(_sock), _sink(_sock), _sock()
+    : _host(host), _port(port), _username(username), _password(password), _filter(_source), _source(_sock), _sink(_sock), _sock()
 {
     _state = MBED_STATE_INIT;
 }
@@ -56,19 +53,20 @@
 
 uint8_t MbedClient::sendData(DataGenerator& generator)
 {
-    char len[8];
+    size_t len; char lenstr[8];
     
     if ((_state != MBED_STATE_IN_REQUEST) && (_state != MBED_STATE_SENT_ID))
         return CLIENT_INTERNAL_ERROR;
     
-    snprintf(len, 8, "%ld", generator.writtenLength());
-
+    len = generator.writtenLength();
+    snprintf(lenstr, 8, "%ld", len);
+    
     if ((!send("Content-Length: ")) ||
-        (!send(len)) ||
+        (!send(lenstr)) ||
         (!send("\r\n\r\n")))
         return CLIENT_CONNECTION_ERROR;
 
-    if (generator.writeTo(_sink) != generator.writtenLength()) {
+    if (generator.writeTo(_sink) != len) {
         stop();
         return CLIENT_CONNECTION_ERROR;
     }
@@ -99,47 +97,10 @@
 
 uint8_t MbedClient::awaitResponse()
 {
-    int8_t state = 0; char c; size_t offset = 0;
-
     if (_state != MBED_STATE_REQ_COMPLETE)
         return CLIENT_INTERNAL_ERROR;
     
-    while ((state >= 0) && (state < 20) && (((c = _source.read()) > 0) || (_source.status() == DS_STATUS_OK))) {
-        switch (state) {
-        case 0: // read expected status line
-            if ((cExpectedStatus[offset] != c) && (cExpectedStatus[offset] != '*'))
-                state = -1;
-            offset++;
-            if (offset == strlen(cExpectedStatus))
-                state = 1;
-            break;
-        linebrk:
-        case 1:
-            if (c == '\n')
-                state = 2;
-            else if (c != '\r')
-                state = -1;
-            break;
-        case 2:
-            if (c == '\n') {
-                state = 20;
-                break;
-            } else if (c == '\r') {
-                break;
-            } else {
-                state = 3;
-                goto random;
-            }
-        random:
-        case 3:
-            if ((c == '\r') || (c == '\n')) {
-                state = 1;
-                goto linebrk;
-            }
-        }
-    }
-    
-    if (state != 20) {
+    if ((_filter.readStatus() != 200) || (!_filter.skipHeaders())) {
         stop();
         return CLIENT_CONNECTION_ERROR;
     }
@@ -150,7 +111,7 @@
 
 AbstractDataSource& MbedClient::receiveData()
 {
-    return _source;
+    return _filter;
 }
 
 void MbedClient::stop()
@@ -158,6 +119,7 @@
     _sock.close();
     _source.reset();
     _sink.reset();
+    _filter.reset();
     _state = MBED_STATE_INIT;
 }
 
--- a/MbedClient.h	Fri Apr 11 09:33:45 2014 +0000
+++ b/MbedClient.h	Mon Apr 14 11:23:50 2014 +0000
@@ -6,6 +6,7 @@
 #include "TCPSocketConnection.h"
 #include "MbedDataSource.h"
 #include "MbedDataSink.h"
+#include "HTTPResponseFilter.h"
 
 #define MBED_STATE_INIT 0
 #define MBED_STATE_IN_REQUEST 1
@@ -38,6 +39,7 @@
     TCPSocketConnection _sock;
     MbedDataSource _source;
     MbedDataSink _sink;
+    HTTPResponseFilter _filter;
 };
 
 #endif
\ No newline at end of file
--- a/MbedDataSink.cpp	Fri Apr 11 09:33:45 2014 +0000
+++ b/MbedDataSink.cpp	Mon Apr 14 11:23:50 2014 +0000
@@ -1,7 +1,6 @@
 #include "MbedDataSink.h"
 #include "MbedClient.h"
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 
 #include "mbed.h"
@@ -21,7 +20,6 @@
             return 0;
     }
     
-    putchar(c);
     _buf[_len++] = c;
     return 1;
 }
@@ -58,7 +56,7 @@
 {
     char str[24];
     
-    snprintf(str, 24, "%uld", number);
+    snprintf(str, 24, "%lu", number);
     return write(str);
 }
 
@@ -78,7 +76,7 @@
     
     if (!_sock.is_connected())
         return false;
-    
+
     _sock.set_blocking(true);
     ret = _sock.send(_buf, _len);