A client for the SmartREST protocol from Cumulocity.

Dependencies:   SmartRest

Fork of MbedSmartRest by Vincent Wochnik

Committer:
vwochnik
Date:
Mon May 26 08:25:44 2014 +0000
Revision:
18:f76f9ae79195
Parent:
14:dc3f8dd5c02b
fix for bootstrapping

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vwochnik 3:ce2f116369bd 1 #include "MbedClient.h"
vwochnik 5:ab909221d22d 2 #include <stdlib.h>
vwochnik 13:e76920d5e1ec 3 #include <string.h>
vwochnik 13:e76920d5e1ec 4 #include "b64.h"
vwochnik 13:e76920d5e1ec 5 #include "mbed.h"
vwochnik 9:3bbb83e7cbfd 6
vwochnik 13:e76920d5e1ec 7 MbedClient::MbedClient(const char* host, uint16_t port, const char* username, const char* password)
vwochnik 14:dc3f8dd5c02b 8 : _host(host), _port(port), _username(username), _password(password), _filter(_source), _source(_sock), _sink(_sock), _sock()
vwochnik 3:ce2f116369bd 9 {
vwochnik 13:e76920d5e1ec 10 _state = MBED_STATE_INIT;
vwochnik 5:ab909221d22d 11 }
vwochnik 5:ab909221d22d 12
vwochnik 5:ab909221d22d 13 MbedClient::~MbedClient()
vwochnik 5:ab909221d22d 14 {
vwochnik 3:ce2f116369bd 15 }
vwochnik 3:ce2f116369bd 16
vwochnik 3:ce2f116369bd 17 uint8_t MbedClient::beginRequest()
vwochnik 3:ce2f116369bd 18 {
vwochnik 13:e76920d5e1ec 19 if (_state != MBED_STATE_INIT)
vwochnik 5:ab909221d22d 20 return CLIENT_INTERNAL_ERROR;
vwochnik 13:e76920d5e1ec 21
vwochnik 13:e76920d5e1ec 22 if (_sock.connect(_host, _port) < 0) {
vwochnik 13:e76920d5e1ec 23 stop();
vwochnik 13:e76920d5e1ec 24 return CLIENT_CONNECTION_ERROR;
vwochnik 13:e76920d5e1ec 25 }
vwochnik 13:e76920d5e1ec 26
vwochnik 13:e76920d5e1ec 27 if ((!send("POST /s HTTP/1.0\r\n")) ||
vwochnik 13:e76920d5e1ec 28 (!send("Host: ")) ||
vwochnik 13:e76920d5e1ec 29 (!send(_host)) ||
vwochnik 13:e76920d5e1ec 30 (!send("\r\n")))
vwochnik 13:e76920d5e1ec 31 return CLIENT_CONNECTION_ERROR;
vwochnik 13:e76920d5e1ec 32
vwochnik 18:f76f9ae79195 33 if ((strlen(_username) > 0) && (strlen(_password) > 0)) {
vwochnik 18:f76f9ae79195 34 if (!sendBasicAuth())
vwochnik 18:f76f9ae79195 35 return CLIENT_CONNECTION_ERROR;
vwochnik 18:f76f9ae79195 36 }
vwochnik 13:e76920d5e1ec 37
vwochnik 13:e76920d5e1ec 38 _state = MBED_STATE_IN_REQUEST;
vwochnik 5:ab909221d22d 39 return CLIENT_OK;
vwochnik 3:ce2f116369bd 40 }
vwochnik 3:ce2f116369bd 41
vwochnik 5:ab909221d22d 42 uint8_t MbedClient::sendIdentifier(const char* identifier)
vwochnik 3:ce2f116369bd 43 {
vwochnik 13:e76920d5e1ec 44 if (_state != MBED_STATE_IN_REQUEST)
vwochnik 5:ab909221d22d 45 return CLIENT_INTERNAL_ERROR;
vwochnik 13:e76920d5e1ec 46
vwochnik 18:f76f9ae79195 47 if ((identifier != NULL) && (strlen(identifier) != 0)) {
vwochnik 18:f76f9ae79195 48 if ((!send("X-Id: ")) ||
vwochnik 18:f76f9ae79195 49 (!send(identifier)) ||
vwochnik 18:f76f9ae79195 50 (!send("\r\n")))
vwochnik 18:f76f9ae79195 51 return CLIENT_CONNECTION_ERROR;
vwochnik 18:f76f9ae79195 52 }
vwochnik 13:e76920d5e1ec 53
vwochnik 13:e76920d5e1ec 54 _state = MBED_STATE_SENT_ID;
vwochnik 5:ab909221d22d 55 return CLIENT_OK;
vwochnik 3:ce2f116369bd 56 }
vwochnik 3:ce2f116369bd 57
vwochnik 3:ce2f116369bd 58 uint8_t MbedClient::sendData(DataGenerator& generator)
vwochnik 3:ce2f116369bd 59 {
vwochnik 14:dc3f8dd5c02b 60 size_t len; char lenstr[8];
vwochnik 13:e76920d5e1ec 61
vwochnik 13:e76920d5e1ec 62 if ((_state != MBED_STATE_IN_REQUEST) && (_state != MBED_STATE_SENT_ID))
vwochnik 5:ab909221d22d 63 return CLIENT_INTERNAL_ERROR;
vwochnik 13:e76920d5e1ec 64
vwochnik 14:dc3f8dd5c02b 65 len = generator.writtenLength();
vwochnik 14:dc3f8dd5c02b 66 snprintf(lenstr, 8, "%ld", len);
vwochnik 14:dc3f8dd5c02b 67
vwochnik 13:e76920d5e1ec 68 if ((!send("Content-Length: ")) ||
vwochnik 14:dc3f8dd5c02b 69 (!send(lenstr)) ||
vwochnik 13:e76920d5e1ec 70 (!send("\r\n\r\n")))
vwochnik 13:e76920d5e1ec 71 return CLIENT_CONNECTION_ERROR;
vwochnik 13:e76920d5e1ec 72
vwochnik 14:dc3f8dd5c02b 73 if (generator.writeTo(_sink) != len) {
vwochnik 13:e76920d5e1ec 74 stop();
vwochnik 13:e76920d5e1ec 75 return CLIENT_CONNECTION_ERROR;
vwochnik 13:e76920d5e1ec 76 }
vwochnik 13:e76920d5e1ec 77
vwochnik 13:e76920d5e1ec 78 _state = MBED_STATE_SENT_DATA;
vwochnik 5:ab909221d22d 79 return CLIENT_OK;
vwochnik 3:ce2f116369bd 80 }
vwochnik 3:ce2f116369bd 81
vwochnik 3:ce2f116369bd 82 uint8_t MbedClient::endRequest()
vwochnik 3:ce2f116369bd 83 {
vwochnik 13:e76920d5e1ec 84 if ((_state != MBED_STATE_IN_REQUEST) && (_state != MBED_STATE_SENT_ID) && (_state != MBED_STATE_SENT_DATA))
vwochnik 5:ab909221d22d 85 return CLIENT_INTERNAL_ERROR;
vwochnik 13:e76920d5e1ec 86
vwochnik 13:e76920d5e1ec 87 if (_state != MBED_STATE_SENT_DATA) {
vwochnik 13:e76920d5e1ec 88 // send end of headers
vwochnik 13:e76920d5e1ec 89 if (!send("\r\n"))
vwochnik 13:e76920d5e1ec 90 return CLIENT_CONNECTION_ERROR;
vwochnik 13:e76920d5e1ec 91 }
vwochnik 13:e76920d5e1ec 92
vwochnik 13:e76920d5e1ec 93 if (!_sink.flush()) {
vwochnik 13:e76920d5e1ec 94 stop();
vwochnik 13:e76920d5e1ec 95 return CLIENT_CONNECTION_ERROR;
vwochnik 13:e76920d5e1ec 96 }
vwochnik 13:e76920d5e1ec 97
vwochnik 13:e76920d5e1ec 98 _state = MBED_STATE_REQ_COMPLETE;
vwochnik 7:26524a6a04a1 99 return CLIENT_OK;
vwochnik 3:ce2f116369bd 100 }
vwochnik 3:ce2f116369bd 101
vwochnik 3:ce2f116369bd 102 uint8_t MbedClient::awaitResponse()
vwochnik 3:ce2f116369bd 103 {
vwochnik 13:e76920d5e1ec 104 if (_state != MBED_STATE_REQ_COMPLETE)
vwochnik 5:ab909221d22d 105 return CLIENT_INTERNAL_ERROR;
vwochnik 13:e76920d5e1ec 106
vwochnik 14:dc3f8dd5c02b 107 if ((_filter.readStatus() != 200) || (!_filter.skipHeaders())) {
vwochnik 13:e76920d5e1ec 108 stop();
vwochnik 5:ab909221d22d 109 return CLIENT_CONNECTION_ERROR;
vwochnik 13:e76920d5e1ec 110 }
vwochnik 13:e76920d5e1ec 111
vwochnik 13:e76920d5e1ec 112 _state = MBED_STATE_RECVD_RESPONSE;
vwochnik 5:ab909221d22d 113 return CLIENT_OK;
vwochnik 3:ce2f116369bd 114 }
vwochnik 3:ce2f116369bd 115
vwochnik 3:ce2f116369bd 116 AbstractDataSource& MbedClient::receiveData()
vwochnik 3:ce2f116369bd 117 {
vwochnik 14:dc3f8dd5c02b 118 return _filter;
vwochnik 3:ce2f116369bd 119 }
vwochnik 3:ce2f116369bd 120
vwochnik 3:ce2f116369bd 121 void MbedClient::stop()
vwochnik 3:ce2f116369bd 122 {
vwochnik 13:e76920d5e1ec 123 _sock.close();
vwochnik 13:e76920d5e1ec 124 _source.reset();
vwochnik 13:e76920d5e1ec 125 _sink.reset();
vwochnik 14:dc3f8dd5c02b 126 _filter.reset();
vwochnik 13:e76920d5e1ec 127 _state = MBED_STATE_INIT;
vwochnik 13:e76920d5e1ec 128 }
vwochnik 13:e76920d5e1ec 129
vwochnik 13:e76920d5e1ec 130 bool MbedClient::send(const char *str)
vwochnik 13:e76920d5e1ec 131 {
vwochnik 13:e76920d5e1ec 132 if (_sink.write(str) != strlen(str)) {
vwochnik 13:e76920d5e1ec 133 stop();
vwochnik 13:e76920d5e1ec 134 return false;
vwochnik 13:e76920d5e1ec 135 }
vwochnik 13:e76920d5e1ec 136 return true;
vwochnik 3:ce2f116369bd 137 }
vwochnik 13:e76920d5e1ec 138
vwochnik 13:e76920d5e1ec 139 bool MbedClient::sendBasicAuth()
vwochnik 13:e76920d5e1ec 140 {
vwochnik 13:e76920d5e1ec 141 size_t ul, pl; unsigned char input[3]; unsigned char output[5];
vwochnik 13:e76920d5e1ec 142 int inputOffset = 0;
vwochnik 13:e76920d5e1ec 143
vwochnik 13:e76920d5e1ec 144 if (!send("Authorization: Basic "))
vwochnik 13:e76920d5e1ec 145 return false;
vwochnik 13:e76920d5e1ec 146
vwochnik 13:e76920d5e1ec 147 ul = strlen(_username);
vwochnik 13:e76920d5e1ec 148 pl = strlen(_password);
vwochnik 13:e76920d5e1ec 149
vwochnik 13:e76920d5e1ec 150 for (int i = 0; i < (ul+1+pl); i++) {
vwochnik 13:e76920d5e1ec 151 if (i < ul)
vwochnik 13:e76920d5e1ec 152 input[inputOffset++] = _username[i];
vwochnik 13:e76920d5e1ec 153 else if (i == ul)
vwochnik 13:e76920d5e1ec 154 input[inputOffset++] = ':';
vwochnik 13:e76920d5e1ec 155 else
vwochnik 13:e76920d5e1ec 156 input[inputOffset++] = _password[i-(ul+1)];
vwochnik 13:e76920d5e1ec 157
vwochnik 13:e76920d5e1ec 158 if ((inputOffset == 3) || (i == ul+pl)) {
vwochnik 13:e76920d5e1ec 159 b64_encode(input, inputOffset, output, 4);
vwochnik 13:e76920d5e1ec 160 output[4] = '\0';
vwochnik 13:e76920d5e1ec 161 if (!send((char*)output))
vwochnik 13:e76920d5e1ec 162 return false;
vwochnik 13:e76920d5e1ec 163 inputOffset = 0;
vwochnik 13:e76920d5e1ec 164 }
vwochnik 13:e76920d5e1ec 165 }
vwochnik 13:e76920d5e1ec 166
vwochnik 13:e76920d5e1ec 167 if (!send("\r\n"))
vwochnik 13:e76920d5e1ec 168 return false;
vwochnik 13:e76920d5e1ec 169 return true;
vwochnik 13:e76920d5e1ec 170 }