branch with improvemnts

Fork of M2XStreamClient by AT&T M2X Team

Committer:
NetArc
Date:
Sun Sep 07 05:28:55 2014 +0000
Revision:
2:7ea7ab05f120
Parent:
0:f479e4f4db0e
Child:
4:ba0d02be2835
fix for parsing numeric stream values

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