A client for the SmartREST protocol from Cumulocity.

Dependencies:   SmartRest

Fork of MbedSmartRest by Vincent Wochnik

Committer:
vwochnik
Date:
Mon Apr 14 11:23:50 2014 +0000
Revision:
14:dc3f8dd5c02b
Parent:
13:e76920d5e1ec
Child:
18:f76f9ae79195
fix

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