mbed.org implementation of the abstract SmartREST library for the Cumulocity Platform SmartREST protocol.

Dependents:   MbedSmartRestMain MbedSmartRestMain

Revision:
0:099f76422485
Child:
1:9a11a331e340
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedClient.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,198 @@
+/*
+ * MbedClient.cpp
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "MbedClient.h"
+#include <stdlib.h>
+#include <string.h>
+#include "b64.h"
+#include "mbed.h"
+
+MbedClient::MbedClient(const char* host, uint16_t port, const char* username, const char* password)
+    : _host(host), _port(port), _username(username), _password(password), _filter(_source), _source(_sock), _sink(_sock), _sock()
+{
+    _state = MBED_STATE_INIT;
+}
+
+MbedClient::~MbedClient()
+{
+}
+
+uint8_t MbedClient::beginRequest()
+{
+    if (_state != MBED_STATE_INIT)
+        return CLIENT_INTERNAL_ERROR;
+
+    if (_sock.connect(_host, _port) < 0) {
+        stop();
+        return CLIENT_CONNECTION_ERROR;
+    }
+
+    if ((!send("POST /s HTTP/1.0\r\n")) ||
+        (!send("Host: ")) ||
+        (!send(_host)) ||
+        (!send("\r\n")))
+        return CLIENT_CONNECTION_ERROR;
+    
+    if ((strlen(_username) > 0) && (strlen(_password) > 0)) {
+        if (!sendBasicAuth())
+            return CLIENT_CONNECTION_ERROR;
+    }
+
+    _state = MBED_STATE_IN_REQUEST;
+    return CLIENT_OK;
+}
+
+uint8_t MbedClient::sendIdentifier(const char* identifier)
+{
+    if (_state != MBED_STATE_IN_REQUEST)
+        return CLIENT_INTERNAL_ERROR;
+
+    if ((identifier != NULL) && (strlen(identifier) != 0)) {
+        if ((!send("X-Id: ")) ||
+            (!send(identifier)) ||
+            (!send("\r\n")))
+            return CLIENT_CONNECTION_ERROR;
+    }
+
+    _state = MBED_STATE_SENT_ID;
+    return CLIENT_OK;
+}
+
+uint8_t MbedClient::sendData(DataGenerator& generator)
+{
+    size_t len; char lenstr[8];
+    
+    if ((_state != MBED_STATE_IN_REQUEST) && (_state != MBED_STATE_SENT_ID))
+        return CLIENT_INTERNAL_ERROR;
+    
+    len = generator.writtenLength();
+    snprintf(lenstr, 8, "%ld", len);
+    
+    if ((!send("Content-Length: ")) ||
+        (!send(lenstr)) ||
+        (!send("\r\n\r\n")))
+        return CLIENT_CONNECTION_ERROR;
+
+    if (generator.writeTo(_sink) != len) {
+        stop();
+        return CLIENT_CONNECTION_ERROR;
+    }
+    
+    _state = MBED_STATE_SENT_DATA;
+    return CLIENT_OK;
+}
+
+uint8_t MbedClient::endRequest()
+{
+    if ((_state != MBED_STATE_IN_REQUEST) && (_state != MBED_STATE_SENT_ID) && (_state != MBED_STATE_SENT_DATA))
+        return CLIENT_INTERNAL_ERROR;
+    
+    if (_state != MBED_STATE_SENT_DATA) {
+        // send end of headers
+        if (!send("\r\n"))
+            return CLIENT_CONNECTION_ERROR;
+    }
+    
+    if (!_sink.flush()) {
+        stop();
+        return CLIENT_CONNECTION_ERROR;
+    }
+    
+    _state = MBED_STATE_REQ_COMPLETE;
+    return CLIENT_OK;
+}
+
+uint8_t MbedClient::awaitResponse()
+{
+    if (_state != MBED_STATE_REQ_COMPLETE)
+        return CLIENT_INTERNAL_ERROR;
+    
+    if ((_filter.readStatus() != 200) || (!_filter.skipHeaders())) {
+        stop();
+        return CLIENT_CONNECTION_ERROR;
+    }
+    
+    _state = MBED_STATE_RECVD_RESPONSE;
+    return CLIENT_OK;
+}
+
+AbstractDataSource& MbedClient::receiveData()
+{
+    return _filter;
+}
+
+void MbedClient::stop()
+{
+    _sock.close();
+    _source.reset();
+    _sink.reset();
+    _filter.reset();
+    _state = MBED_STATE_INIT;
+}
+
+bool MbedClient::send(const char *str)
+{
+    if (_sink.write(str) != strlen(str)) {
+        stop();
+        return false;
+    }
+    return true;
+}
+
+bool MbedClient::sendBasicAuth()
+{
+    size_t ul, pl; unsigned char input[3]; unsigned char output[5];
+    int inputOffset = 0;
+
+    if (!send("Authorization: Basic "))
+        return false;
+        
+    ul = strlen(_username);
+    pl = strlen(_password);
+
+    for (int i = 0; i < (ul+1+pl); i++) {
+        if (i < ul)
+            input[inputOffset++] = _username[i];
+        else if (i == ul)
+            input[inputOffset++] = ':';
+        else
+            input[inputOffset++] = _password[i-(ul+1)];
+
+        if ((inputOffset == 3) || (i == ul+pl)) {
+            b64_encode(input, inputOffset, output, 4);
+            output[4] = '\0';
+            if (!send((char*)output))
+                return false;
+            inputOffset = 0;
+        }
+    }
+    
+    if (!send("\r\n"))
+        return false;
+    return true;
+}