branch with improvemnts

Fork of M2XStreamClient by AT&T M2X Team

Committer:
mazgch
Date:
Sat Sep 13 15:49:53 2014 +0000
Revision:
11:5c71c2948812
Parent:
10:4ce9eba38dbe
use local buffers and the flush or fill

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jb8414 0:f479e4f4db0e 1 #include "M2XStreamClient.h"
jb8414 0:f479e4f4db0e 2
jb8414 0:f479e4f4db0e 3 #include <jsonlite.h>
jb8414 0:f479e4f4db0e 4
jb8414 0:f479e4f4db0e 5 #include "StreamParseFunctions.h"
jb8414 0:f479e4f4db0e 6 #include "LocationParseFunctions.h"
jb8414 0:f479e4f4db0e 7
jb8414 0:f479e4f4db0e 8 const char* M2XStreamClient::kDefaultM2XHost = "api-m2x.att.com";
jb8414 0:f479e4f4db0e 9
citrusbyte 10:4ce9eba38dbe 10 static int write_delete_values(Print* print, const char* from, const char* end);
jb8414 0:f479e4f4db0e 11 int print_encoded_string(Print* print, const char* str);
jb8414 0:f479e4f4db0e 12 int tolower(int ch);
jb8414 0:f479e4f4db0e 13
jb8414 0:f479e4f4db0e 14 #if defined(ARDUINO_PLATFORM) || defined(MBED_PLATFORM)
jb8414 0:f479e4f4db0e 15 int tolower(int ch)
jb8414 0:f479e4f4db0e 16 {
jb8414 0:f479e4f4db0e 17 // Arduino and mbed use ASCII table, so we can simplify the implementation
jb8414 0:f479e4f4db0e 18 if ((ch >= 'A') && (ch <= 'Z')) {
jb8414 0:f479e4f4db0e 19 return (ch + 32);
jb8414 0:f479e4f4db0e 20 }
jb8414 0:f479e4f4db0e 21 return ch;
jb8414 0:f479e4f4db0e 22 }
jb8414 0:f479e4f4db0e 23 #else
jb8414 0:f479e4f4db0e 24 // For other platform, we use libc's tolower by default
jb8414 0:f479e4f4db0e 25 #include <ctype.h>
jb8414 0:f479e4f4db0e 26 #endif
jb8414 0:f479e4f4db0e 27
jb8414 0:f479e4f4db0e 28 M2XStreamClient::M2XStreamClient(Client* client,
jb8414 0:f479e4f4db0e 29 const char* key,
jb8414 0:f479e4f4db0e 30 int case_insensitive,
jb8414 0:f479e4f4db0e 31 const char* host,
jb8414 0:f479e4f4db0e 32 int port) : _client(client),
jb8414 0:f479e4f4db0e 33 _key(key),
jb8414 0:f479e4f4db0e 34 _case_insensitive(case_insensitive),
jb8414 0:f479e4f4db0e 35 _host(host),
jb8414 0:f479e4f4db0e 36 _port(port),
jb8414 0:f479e4f4db0e 37 _null_print() {
jb8414 0:f479e4f4db0e 38 }
jb8414 0:f479e4f4db0e 39
jb8414 0:f479e4f4db0e 40 #define WRITE_QUERY_PART(client_, started_, name_, str_) { \
jb8414 0:f479e4f4db0e 41 if (str_) { \
jb8414 0:f479e4f4db0e 42 if (started_) { \
jb8414 0:f479e4f4db0e 43 (client_)->print("&"); \
jb8414 0:f479e4f4db0e 44 } else { \
jb8414 0:f479e4f4db0e 45 (client_)->print("?"); \
jb8414 0:f479e4f4db0e 46 started_ = true; \
jb8414 0:f479e4f4db0e 47 } \
jb8414 0:f479e4f4db0e 48 (client_)->print(name_ "="); \
jb8414 0:f479e4f4db0e 49 (client_)->print(str_); \
jb8414 0:f479e4f4db0e 50 } \
jb8414 0:f479e4f4db0e 51 }
jb8414 0:f479e4f4db0e 52
jb8414 0:f479e4f4db0e 53 int M2XStreamClient::fetchValues(const char* feedId, const char* streamName,
jb8414 0:f479e4f4db0e 54 stream_value_read_callback callback, void* context,
jb8414 0:f479e4f4db0e 55 const char* startTime, const char* endTime,
jb8414 0:f479e4f4db0e 56 const char* limit) {
jb8414 0:f479e4f4db0e 57 if (_client->connect(_host, _port)) {
jb8414 0:f479e4f4db0e 58 bool query_started = false;
jb8414 0:f479e4f4db0e 59
jb8414 0:f479e4f4db0e 60 DBGLN("%s", "Connected to M2X server!");
jb8414 0:f479e4f4db0e 61 _client->print("GET /v1/feeds/");
jb8414 0:f479e4f4db0e 62 print_encoded_string(_client, feedId);
jb8414 0:f479e4f4db0e 63 _client->print("/streams/");
jb8414 0:f479e4f4db0e 64 print_encoded_string(_client, streamName);
jb8414 0:f479e4f4db0e 65 _client->print("/values");
jb8414 0:f479e4f4db0e 66
jb8414 0:f479e4f4db0e 67 WRITE_QUERY_PART(_client, query_started, "start", startTime);
jb8414 0:f479e4f4db0e 68 WRITE_QUERY_PART(_client, query_started, "end", endTime);
jb8414 0:f479e4f4db0e 69 WRITE_QUERY_PART(_client, query_started, "limit", limit);
jb8414 0:f479e4f4db0e 70
jb8414 0:f479e4f4db0e 71 _client->println(" HTTP/1.0");
jb8414 0:f479e4f4db0e 72 writeHttpHeader(-1);
jb8414 0:f479e4f4db0e 73 } else {
jb8414 0:f479e4f4db0e 74 DBGLN("%s", "ERROR: Cannot connect to M2X server!");
jb8414 0:f479e4f4db0e 75 return E_NOCONNECTION;
jb8414 0:f479e4f4db0e 76 }
jb8414 0:f479e4f4db0e 77 int status = readStatusCode(false);
jb8414 0:f479e4f4db0e 78 if (status == 200) {
jb8414 0:f479e4f4db0e 79 readStreamValue(callback, context);
jb8414 0:f479e4f4db0e 80 }
jb8414 0:f479e4f4db0e 81
jb8414 0:f479e4f4db0e 82 close();
jb8414 0:f479e4f4db0e 83 return status;
jb8414 0:f479e4f4db0e 84 }
jb8414 0:f479e4f4db0e 85
jb8414 0:f479e4f4db0e 86 int M2XStreamClient::readLocation(const char* feedId,
jb8414 0:f479e4f4db0e 87 location_read_callback callback,
jb8414 0:f479e4f4db0e 88 void* context) {
jb8414 0:f479e4f4db0e 89 if (_client->connect(_host, _port)) {
jb8414 0:f479e4f4db0e 90 DBGLN("%s", "Connected to M2X server!");
jb8414 0:f479e4f4db0e 91 _client->print("GET /v1/feeds/");
jb8414 0:f479e4f4db0e 92 print_encoded_string(_client, feedId);
jb8414 0:f479e4f4db0e 93 _client->println("/location HTTP/1.0");
jb8414 0:f479e4f4db0e 94
jb8414 0:f479e4f4db0e 95 writeHttpHeader(-1);
jb8414 0:f479e4f4db0e 96 } else {
jb8414 0:f479e4f4db0e 97 DBGLN("%s", "ERROR: Cannot connect to M2X server!");
jb8414 0:f479e4f4db0e 98 return E_NOCONNECTION;
jb8414 0:f479e4f4db0e 99 }
jb8414 0:f479e4f4db0e 100 int status = readStatusCode(false);
jb8414 0:f479e4f4db0e 101 if (status == 200) {
jb8414 0:f479e4f4db0e 102 readLocation(callback, context);
jb8414 0:f479e4f4db0e 103 }
jb8414 0:f479e4f4db0e 104
jb8414 0:f479e4f4db0e 105 close();
jb8414 0:f479e4f4db0e 106 return status;
jb8414 0:f479e4f4db0e 107 }
jb8414 0:f479e4f4db0e 108
citrusbyte 10:4ce9eba38dbe 109 int M2XStreamClient::deleteValues(const char* feedId, const char* streamName,
citrusbyte 10:4ce9eba38dbe 110 const char* from, const char* end) {
citrusbyte 10:4ce9eba38dbe 111 if (_client->connect(_host, _port)) {
citrusbyte 10:4ce9eba38dbe 112 DBGLN("%s", "Connected to M2X server!");
citrusbyte 10:4ce9eba38dbe 113 int length = write_delete_values(&_null_print, from, end);
citrusbyte 10:4ce9eba38dbe 114 writeDeleteHeader(feedId, streamName, length);
citrusbyte 10:4ce9eba38dbe 115 write_delete_values(_client, from, end);
citrusbyte 10:4ce9eba38dbe 116 } else {
citrusbyte 10:4ce9eba38dbe 117 DBGLN("%s", "ERROR: Cannot connect to M2X server!");
citrusbyte 10:4ce9eba38dbe 118 return E_NOCONNECTION;
citrusbyte 10:4ce9eba38dbe 119 }
citrusbyte 10:4ce9eba38dbe 120
citrusbyte 10:4ce9eba38dbe 121 return readStatusCode(true);
citrusbyte 10:4ce9eba38dbe 122 }
citrusbyte 10:4ce9eba38dbe 123
citrusbyte 10:4ce9eba38dbe 124 static int write_delete_values(Print* print, const char* from,
citrusbyte 10:4ce9eba38dbe 125 const char* end) {
citrusbyte 10:4ce9eba38dbe 126 int bytes = 0;
citrusbyte 10:4ce9eba38dbe 127 bytes += print->print("{\"from\":\"");
citrusbyte 10:4ce9eba38dbe 128 bytes += print->print(from);
citrusbyte 10:4ce9eba38dbe 129 bytes += print->print("\",\"end\":\"");
citrusbyte 10:4ce9eba38dbe 130 bytes += print->print(end);
citrusbyte 10:4ce9eba38dbe 131 bytes += print->print("\"}");
citrusbyte 10:4ce9eba38dbe 132 return bytes;
citrusbyte 10:4ce9eba38dbe 133 }
citrusbyte 10:4ce9eba38dbe 134
jb8414 0:f479e4f4db0e 135 // Encodes and prints string using Percent-encoding specified
jb8414 0:f479e4f4db0e 136 // in RFC 1738, Section 2.2
jb8414 0:f479e4f4db0e 137 int print_encoded_string(Print* print, const char* str) {
jb8414 0:f479e4f4db0e 138 int bytes = 0;
jb8414 0:f479e4f4db0e 139 for (int i = 0; str[i] != 0; i++) {
jb8414 0:f479e4f4db0e 140 if (((str[i] >= 'A') && (str[i] <= 'Z')) ||
jb8414 0:f479e4f4db0e 141 ((str[i] >= 'a') && (str[i] <= 'z')) ||
jb8414 0:f479e4f4db0e 142 ((str[i] >= '0') && (str[i] <= '9')) ||
jb8414 0:f479e4f4db0e 143 (str[i] == '-') || (str[i] == '_') ||
jb8414 0:f479e4f4db0e 144 (str[i] == '.') || (str[i] == '~')) {
jb8414 0:f479e4f4db0e 145 bytes += print->print(str[i]);
jb8414 0:f479e4f4db0e 146 } else {
jb8414 0:f479e4f4db0e 147 // Encode all other characters
jb8414 0:f479e4f4db0e 148 bytes += print->print('%');
jb8414 0:f479e4f4db0e 149 bytes += print->print(HEX(str[i] / 16));
jb8414 0:f479e4f4db0e 150 bytes += print->print(HEX(str[i] % 16));
jb8414 0:f479e4f4db0e 151 }
jb8414 0:f479e4f4db0e 152 }
jb8414 0:f479e4f4db0e 153 return bytes;
jb8414 0:f479e4f4db0e 154 }
jb8414 0:f479e4f4db0e 155
citrusbyte 10:4ce9eba38dbe 156 void M2XStreamClient::writePutHeader(const char* feedId,
citrusbyte 10:4ce9eba38dbe 157 const char* streamName,
citrusbyte 10:4ce9eba38dbe 158 int contentLength) {
jb8414 0:f479e4f4db0e 159 _client->print("PUT /v1/feeds/");
jb8414 0:f479e4f4db0e 160 print_encoded_string(_client, feedId);
jb8414 0:f479e4f4db0e 161 _client->print("/streams/");
jb8414 0:f479e4f4db0e 162 print_encoded_string(_client, streamName);
jb8414 0:f479e4f4db0e 163 _client->println(" HTTP/1.0");
jb8414 0:f479e4f4db0e 164
jb8414 0:f479e4f4db0e 165 writeHttpHeader(contentLength);
jb8414 0:f479e4f4db0e 166 }
jb8414 0:f479e4f4db0e 167
citrusbyte 10:4ce9eba38dbe 168 void M2XStreamClient::writeDeleteHeader(const char* feedId,
citrusbyte 10:4ce9eba38dbe 169 const char* streamName,
citrusbyte 10:4ce9eba38dbe 170 int contentLength) {
citrusbyte 10:4ce9eba38dbe 171 _client->print("DELETE /v1/feeds/");
citrusbyte 10:4ce9eba38dbe 172 print_encoded_string(_client, feedId);
citrusbyte 10:4ce9eba38dbe 173 _client->print("/streams/");
citrusbyte 10:4ce9eba38dbe 174 print_encoded_string(_client, streamName);
citrusbyte 10:4ce9eba38dbe 175 _client->print("/values");
citrusbyte 10:4ce9eba38dbe 176 _client->println(" HTTP/1.0");
citrusbyte 10:4ce9eba38dbe 177
citrusbyte 10:4ce9eba38dbe 178 writeHttpHeader(contentLength);
citrusbyte 10:4ce9eba38dbe 179 }
citrusbyte 10:4ce9eba38dbe 180
jb8414 0:f479e4f4db0e 181 void M2XStreamClient::writeHttpHeader(int contentLength) {
jb8414 0:f479e4f4db0e 182 _client->println(USER_AGENT);
jb8414 0:f479e4f4db0e 183 _client->print("X-M2X-KEY: ");
jb8414 0:f479e4f4db0e 184 _client->println(_key);
jb8414 0:f479e4f4db0e 185
jb8414 0:f479e4f4db0e 186 _client->print("Host: ");
jb8414 0:f479e4f4db0e 187 print_encoded_string(_client, _host);
jb8414 0:f479e4f4db0e 188 if (_port != kDefaultM2XPort) {
jb8414 0:f479e4f4db0e 189 _client->print(":");
jb8414 0:f479e4f4db0e 190 // port is an integer, does not need encoding
jb8414 0:f479e4f4db0e 191 _client->print(_port);
jb8414 0:f479e4f4db0e 192 }
jb8414 0:f479e4f4db0e 193 _client->println();
jb8414 0:f479e4f4db0e 194
jb8414 0:f479e4f4db0e 195 if (contentLength > 0) {
jb8414 0:f479e4f4db0e 196 _client->println("Content-Type: application/json");
jb8414 0:f479e4f4db0e 197 DBG("%s", "Content Length: ");
jb8414 0:f479e4f4db0e 198 DBGLN("%d", contentLength);
jb8414 0:f479e4f4db0e 199
jb8414 0:f479e4f4db0e 200 _client->print("Content-Length: ");
jb8414 0:f479e4f4db0e 201 _client->println(contentLength);
jb8414 0:f479e4f4db0e 202 }
jb8414 0:f479e4f4db0e 203 _client->println();
jb8414 0:f479e4f4db0e 204 }
jb8414 0:f479e4f4db0e 205
jb8414 0:f479e4f4db0e 206 int M2XStreamClient::waitForString(const char* str) {
jb8414 0:f479e4f4db0e 207 int currentIndex = 0;
jb8414 0:f479e4f4db0e 208 if (str[currentIndex] == '\0') return E_OK;
jb8414 0:f479e4f4db0e 209
jb8414 0:f479e4f4db0e 210 while (true) {
jb8414 0:f479e4f4db0e 211 while (_client->available()) {
jb8414 0:f479e4f4db0e 212 char c = _client->read();
jb8414 0:f479e4f4db0e 213 DBG("%c", c);
jb8414 0:f479e4f4db0e 214
jb8414 0:f479e4f4db0e 215 int cmp;
jb8414 0:f479e4f4db0e 216 if (_case_insensitive) {
jb8414 0:f479e4f4db0e 217 cmp = tolower(c) - tolower(str[currentIndex]);
jb8414 0:f479e4f4db0e 218 } else {
jb8414 0:f479e4f4db0e 219 cmp = c - str[currentIndex];
jb8414 0:f479e4f4db0e 220 }
jb8414 0:f479e4f4db0e 221
jb8414 0:f479e4f4db0e 222 if ((str[currentIndex] == '*') || (cmp == 0)) {
jb8414 0:f479e4f4db0e 223 currentIndex++;
jb8414 0:f479e4f4db0e 224 if (str[currentIndex] == '\0') {
jb8414 0:f479e4f4db0e 225 return E_OK;
jb8414 0:f479e4f4db0e 226 }
jb8414 0:f479e4f4db0e 227 } else {
jb8414 0:f479e4f4db0e 228 // start from the beginning
jb8414 0:f479e4f4db0e 229 currentIndex = 0;
jb8414 0:f479e4f4db0e 230 }
jb8414 0:f479e4f4db0e 231 }
jb8414 0:f479e4f4db0e 232
jb8414 0:f479e4f4db0e 233 if (!_client->connected()) {
jb8414 0:f479e4f4db0e 234 DBGLN("%s", "ERROR: The client is disconnected from the server!");
jb8414 0:f479e4f4db0e 235
jb8414 0:f479e4f4db0e 236 close();
jb8414 0:f479e4f4db0e 237 return E_DISCONNECTED;
jb8414 0:f479e4f4db0e 238 }
jb8414 0:f479e4f4db0e 239
jb8414 0:f479e4f4db0e 240 delay(1000);
jb8414 0:f479e4f4db0e 241 }
jb8414 0:f479e4f4db0e 242 // never reached here
jb8414 0:f479e4f4db0e 243 return E_NOTREACHABLE;
jb8414 0:f479e4f4db0e 244 }
jb8414 0:f479e4f4db0e 245
jb8414 0:f479e4f4db0e 246 int M2XStreamClient::readStatusCode(bool closeClient) {
jb8414 0:f479e4f4db0e 247 int responseCode = 0;
jb8414 0:f479e4f4db0e 248 int ret = waitForString("HTTP/*.* ");
jb8414 0:f479e4f4db0e 249 if (ret != E_OK) {
jb8414 0:f479e4f4db0e 250 if (closeClient) close();
jb8414 0:f479e4f4db0e 251 return ret;
jb8414 0:f479e4f4db0e 252 }
jb8414 0:f479e4f4db0e 253
jb8414 0:f479e4f4db0e 254 // ret is not needed from here(since it must be E_OK), so we can use it
jb8414 0:f479e4f4db0e 255 // as a regular variable now.
jb8414 0:f479e4f4db0e 256 ret = 0;
jb8414 0:f479e4f4db0e 257 while (true) {
jb8414 0:f479e4f4db0e 258 while (_client->available()) {
jb8414 0:f479e4f4db0e 259 char c = _client->read();
jb8414 0:f479e4f4db0e 260 DBG("%c", c);
jb8414 0:f479e4f4db0e 261
jb8414 0:f479e4f4db0e 262 responseCode = responseCode * 10 + (c - '0');
jb8414 0:f479e4f4db0e 263 ret++;
jb8414 0:f479e4f4db0e 264 if (ret == 3) {
jb8414 0:f479e4f4db0e 265 if (closeClient) close();
jb8414 0:f479e4f4db0e 266 return responseCode;
jb8414 0:f479e4f4db0e 267 }
jb8414 0:f479e4f4db0e 268 }
jb8414 0:f479e4f4db0e 269
jb8414 0:f479e4f4db0e 270 if (!_client->connected()) {
jb8414 0:f479e4f4db0e 271 DBGLN("%s", "ERROR: The client is disconnected from the server!");
jb8414 0:f479e4f4db0e 272
jb8414 0:f479e4f4db0e 273 if (closeClient) close();
jb8414 0:f479e4f4db0e 274 return E_DISCONNECTED;
jb8414 0:f479e4f4db0e 275 }
jb8414 0:f479e4f4db0e 276
jb8414 0:f479e4f4db0e 277 delay(1000);
jb8414 0:f479e4f4db0e 278 }
jb8414 0:f479e4f4db0e 279
jb8414 0:f479e4f4db0e 280 // never reached here
jb8414 0:f479e4f4db0e 281 return E_NOTREACHABLE;
jb8414 0:f479e4f4db0e 282 }
jb8414 0:f479e4f4db0e 283
jb8414 0:f479e4f4db0e 284 int M2XStreamClient::readContentLength() {
jb8414 0:f479e4f4db0e 285 int ret = waitForString("Content-Length: ");
jb8414 0:f479e4f4db0e 286 if (ret != E_OK) {
jb8414 0:f479e4f4db0e 287 return ret;
jb8414 0:f479e4f4db0e 288 }
jb8414 0:f479e4f4db0e 289
jb8414 0:f479e4f4db0e 290 // From now on, ret is not needed, we can use it
jb8414 0:f479e4f4db0e 291 // to keep the final result
jb8414 0:f479e4f4db0e 292 ret = 0;
jb8414 0:f479e4f4db0e 293 while (true) {
jb8414 0:f479e4f4db0e 294 while (_client->available()) {
jb8414 0:f479e4f4db0e 295 char c = _client->read();
jb8414 0:f479e4f4db0e 296 DBG("%c", c);
jb8414 0:f479e4f4db0e 297
jb8414 0:f479e4f4db0e 298 if ((c == '\r') || (c == '\n')) {
jb8414 0:f479e4f4db0e 299 return (ret == 0) ? (E_INVALID) : (ret);
jb8414 0:f479e4f4db0e 300 } else {
jb8414 0:f479e4f4db0e 301 ret = ret * 10 + (c - '0');
jb8414 0:f479e4f4db0e 302 }
jb8414 0:f479e4f4db0e 303 }
jb8414 0:f479e4f4db0e 304
jb8414 0:f479e4f4db0e 305 if (!_client->connected()) {
jb8414 0:f479e4f4db0e 306 DBGLN("%s", "ERROR: The client is disconnected from the server!");
jb8414 0:f479e4f4db0e 307
jb8414 0:f479e4f4db0e 308 return E_DISCONNECTED;
jb8414 0:f479e4f4db0e 309 }
jb8414 0:f479e4f4db0e 310
jb8414 0:f479e4f4db0e 311 delay(1000);
jb8414 0:f479e4f4db0e 312 }
jb8414 0:f479e4f4db0e 313
jb8414 0:f479e4f4db0e 314 // never reached here
jb8414 0:f479e4f4db0e 315 return E_NOTREACHABLE;
jb8414 0:f479e4f4db0e 316 }
jb8414 0:f479e4f4db0e 317
jb8414 0:f479e4f4db0e 318 int M2XStreamClient::skipHttpHeader() {
jb8414 0:f479e4f4db0e 319 return waitForString("\r\n\r\n");
jb8414 0:f479e4f4db0e 320 }
jb8414 0:f479e4f4db0e 321
jb8414 0:f479e4f4db0e 322 void M2XStreamClient::close() {
jb8414 0:f479e4f4db0e 323 // Eats up buffered data before closing
jb8414 0:f479e4f4db0e 324 _client->flush();
jb8414 0:f479e4f4db0e 325 _client->stop();
jb8414 0:f479e4f4db0e 326 }
jb8414 0:f479e4f4db0e 327
jb8414 0:f479e4f4db0e 328 int M2XStreamClient::readStreamValue(stream_value_read_callback callback,
jb8414 0:f479e4f4db0e 329 void* context) {
NetArc 2:7ea7ab05f120 330 const int BUF_LEN = 64;
jb8414 0:f479e4f4db0e 331 char buf[BUF_LEN];
jb8414 0:f479e4f4db0e 332
jb8414 0:f479e4f4db0e 333 int length = readContentLength();
jb8414 0:f479e4f4db0e 334 if (length < 0) {
jb8414 0:f479e4f4db0e 335 close();
jb8414 0:f479e4f4db0e 336 return length;
jb8414 0:f479e4f4db0e 337 }
jb8414 0:f479e4f4db0e 338
jb8414 0:f479e4f4db0e 339 int index = skipHttpHeader();
jb8414 0:f479e4f4db0e 340 if (index != E_OK) {
jb8414 0:f479e4f4db0e 341 close();
jb8414 0:f479e4f4db0e 342 return index;
jb8414 0:f479e4f4db0e 343 }
jb8414 0:f479e4f4db0e 344 index = 0;
jb8414 0:f479e4f4db0e 345
jb8414 0:f479e4f4db0e 346 stream_parsing_context_state state;
jb8414 0:f479e4f4db0e 347 state.state = state.index = 0;
jb8414 0:f479e4f4db0e 348 state.callback = callback;
jb8414 0:f479e4f4db0e 349 state.context = context;
jb8414 0:f479e4f4db0e 350
jb8414 0:f479e4f4db0e 351 jsonlite_parser_callbacks cbs = jsonlite_default_callbacks;
jb8414 0:f479e4f4db0e 352 cbs.key_found = on_stream_key_found;
citrusbyte 10:4ce9eba38dbe 353 cbs.number_found = on_stream_number_found;
jb8414 0:f479e4f4db0e 354 cbs.string_found = on_stream_string_found;
jb8414 0:f479e4f4db0e 355 cbs.context.client_state = &state;
jb8414 0:f479e4f4db0e 356
jb8414 0:f479e4f4db0e 357 jsonlite_parser p = jsonlite_parser_init(jsonlite_parser_estimate_size(5));
jb8414 0:f479e4f4db0e 358 jsonlite_parser_set_callback(p, &cbs);
jb8414 0:f479e4f4db0e 359
jb8414 0:f479e4f4db0e 360 jsonlite_result result = jsonlite_result_unknown;
jb8414 0:f479e4f4db0e 361 while (index < length) {
jb8414 0:f479e4f4db0e 362 int i = 0;
citrusbyte 10:4ce9eba38dbe 363
jb8414 0:f479e4f4db0e 364 DBG("%s", "Received Data: ");
jb8414 0:f479e4f4db0e 365 while ((i < BUF_LEN) && _client->available()) {
jb8414 0:f479e4f4db0e 366 buf[i++] = _client->read();
jb8414 0:f479e4f4db0e 367 DBG("%c", buf[i - 1]);
jb8414 0:f479e4f4db0e 368 }
jb8414 0:f479e4f4db0e 369 DBGLNEND;
jb8414 0:f479e4f4db0e 370
jb8414 0:f479e4f4db0e 371 if ((!_client->connected()) &&
jb8414 0:f479e4f4db0e 372 (!_client->available()) &&
jb8414 0:f479e4f4db0e 373 ((index + i) < length)) {
jb8414 0:f479e4f4db0e 374 jsonlite_parser_release(p);
jb8414 0:f479e4f4db0e 375 close();
jb8414 0:f479e4f4db0e 376 return E_NOCONNECTION;
jb8414 0:f479e4f4db0e 377 }
jb8414 0:f479e4f4db0e 378
jb8414 0:f479e4f4db0e 379 result = jsonlite_parser_tokenize(p, buf, i);
jb8414 0:f479e4f4db0e 380 if ((result != jsonlite_result_ok) &&
jb8414 0:f479e4f4db0e 381 (result != jsonlite_result_end_of_stream)) {
jb8414 0:f479e4f4db0e 382 jsonlite_parser_release(p);
jb8414 0:f479e4f4db0e 383 close();
jb8414 0:f479e4f4db0e 384 return E_JSON_INVALID;
jb8414 0:f479e4f4db0e 385 }
citrusbyte 10:4ce9eba38dbe 386
NetArc 4:ba0d02be2835 387 index += i;
jb8414 0:f479e4f4db0e 388 }
jb8414 0:f479e4f4db0e 389
jb8414 0:f479e4f4db0e 390 jsonlite_parser_release(p);
jb8414 0:f479e4f4db0e 391 close();
jb8414 0:f479e4f4db0e 392 return (result == jsonlite_result_ok) ? (E_OK) : (E_JSON_INVALID);
jb8414 0:f479e4f4db0e 393 }
jb8414 0:f479e4f4db0e 394
jb8414 0:f479e4f4db0e 395 int M2XStreamClient::readLocation(location_read_callback callback,
jb8414 0:f479e4f4db0e 396 void* context) {
jb8414 0:f479e4f4db0e 397 const int BUF_LEN = 40;
jb8414 0:f479e4f4db0e 398 char buf[BUF_LEN];
jb8414 0:f479e4f4db0e 399
jb8414 0:f479e4f4db0e 400 int length = readContentLength();
jb8414 0:f479e4f4db0e 401 if (length < 0) {
jb8414 0:f479e4f4db0e 402 close();
jb8414 0:f479e4f4db0e 403 return length;
jb8414 0:f479e4f4db0e 404 }
jb8414 0:f479e4f4db0e 405
jb8414 0:f479e4f4db0e 406 int index = skipHttpHeader();
jb8414 0:f479e4f4db0e 407 if (index != E_OK) {
jb8414 0:f479e4f4db0e 408 close();
jb8414 0:f479e4f4db0e 409 return index;
jb8414 0:f479e4f4db0e 410 }
jb8414 0:f479e4f4db0e 411 index = 0;
jb8414 0:f479e4f4db0e 412
jb8414 0:f479e4f4db0e 413 location_parsing_context_state state;
jb8414 0:f479e4f4db0e 414 state.state = state.index = 0;
jb8414 0:f479e4f4db0e 415 state.callback = callback;
jb8414 0:f479e4f4db0e 416 state.context = context;
jb8414 0:f479e4f4db0e 417
jb8414 0:f479e4f4db0e 418 jsonlite_parser_callbacks cbs = jsonlite_default_callbacks;
jb8414 0:f479e4f4db0e 419 cbs.key_found = on_location_key_found;
jb8414 0:f479e4f4db0e 420 cbs.string_found = on_location_string_found;
jb8414 0:f479e4f4db0e 421 cbs.context.client_state = &state;
jb8414 0:f479e4f4db0e 422
jb8414 0:f479e4f4db0e 423 jsonlite_parser p = jsonlite_parser_init(jsonlite_parser_estimate_size(5));
jb8414 0:f479e4f4db0e 424 jsonlite_parser_set_callback(p, &cbs);
jb8414 0:f479e4f4db0e 425
jb8414 0:f479e4f4db0e 426 jsonlite_result result = jsonlite_result_unknown;
jb8414 0:f479e4f4db0e 427 while (index < length) {
jb8414 0:f479e4f4db0e 428 int i = 0;
jb8414 0:f479e4f4db0e 429
jb8414 0:f479e4f4db0e 430 DBG("%s", "Received Data: ");
jb8414 0:f479e4f4db0e 431 while ((i < BUF_LEN) && _client->available()) {
jb8414 0:f479e4f4db0e 432 buf[i++] = _client->read();
jb8414 0:f479e4f4db0e 433 DBG("%c", buf[i - 1]);
jb8414 0:f479e4f4db0e 434 }
jb8414 0:f479e4f4db0e 435 DBGLNEND;
jb8414 0:f479e4f4db0e 436
jb8414 0:f479e4f4db0e 437 if ((!_client->connected()) &&
jb8414 0:f479e4f4db0e 438 (!_client->available()) &&
jb8414 0:f479e4f4db0e 439 ((index + i) < length)) {
jb8414 0:f479e4f4db0e 440 jsonlite_parser_release(p);
jb8414 0:f479e4f4db0e 441 close();
jb8414 0:f479e4f4db0e 442 return E_NOCONNECTION;
jb8414 0:f479e4f4db0e 443 }
jb8414 0:f479e4f4db0e 444
jb8414 0:f479e4f4db0e 445 result = jsonlite_parser_tokenize(p, buf, i);
jb8414 0:f479e4f4db0e 446 if ((result != jsonlite_result_ok) &&
jb8414 0:f479e4f4db0e 447 (result != jsonlite_result_end_of_stream)) {
jb8414 0:f479e4f4db0e 448 jsonlite_parser_release(p);
jb8414 0:f479e4f4db0e 449 close();
jb8414 0:f479e4f4db0e 450 return E_JSON_INVALID;
jb8414 0:f479e4f4db0e 451 }
jb8414 0:f479e4f4db0e 452
jb8414 0:f479e4f4db0e 453 index += i;
jb8414 0:f479e4f4db0e 454 }
jb8414 0:f479e4f4db0e 455
jb8414 0:f479e4f4db0e 456 jsonlite_parser_release(p);
jb8414 0:f479e4f4db0e 457 close();
jb8414 0:f479e4f4db0e 458 return (result == jsonlite_result_ok) ? (E_OK) : (E_JSON_INVALID);
jb8414 0:f479e4f4db0e 459 }