Modified PubNub library to better utilize low bandwidth connections like a GSM modem. Instead of 10 socket connections sending 3 bytes only one is made and it sends all 30 bytes at the same time.
Fork of PubNub by
PubNub.cpp@7:55eb53c78b47, 2014-10-01 (annotated)
- Committer:
- embeddedartists
- Date:
- Wed Oct 01 11:36:11 2014 +0000
- Revision:
- 7:55eb53c78b47
- Parent:
- 6:09d0a383fdde
Modified PubNub library to better utilize low bandwidth connections like a GSM modem. Instead of 10 sockets connections sending 3 bytes only one is made and it sends all 30 bytes at the same time.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
pasky | 0:9858347c382d | 1 | #include <cstring> |
pasky | 0:9858347c382d | 2 | |
pasky | 0:9858347c382d | 3 | #include "mbed.h" |
mazgch | 6:09d0a383fdde | 4 | #include "TCPSocketConnection.h" |
pasky | 0:9858347c382d | 5 | |
pasky | 0:9858347c382d | 6 | #include "PubNub.h" |
pasky | 0:9858347c382d | 7 | |
pasky | 0:9858347c382d | 8 | |
pasky | 0:9858347c382d | 9 | #define DBG if (0) // change to if (1) to enable debug prints on USB serial |
pasky | 0:9858347c382d | 10 | |
embeddedartists | 7:55eb53c78b47 | 11 | //#define USE_ORIGINAL_CODE |
pasky | 0:9858347c382d | 12 | |
pasky | 0:9858347c382d | 13 | /* We roll our own HTTP communication stack as donatien's HTTPClient has |
pasky | 0:9858347c382d | 14 | * some hard limits on URL length and this will allow a more frugal RAM |
pasky | 0:9858347c382d | 15 | * usage for us. */ |
pasky | 0:9858347c382d | 16 | |
pasky | 0:9858347c382d | 17 | /* Also, we pass messages as serialized JSON strings instead of parsed |
pasky | 0:9858347c382d | 18 | * structures. The available JSON parsers (picojson in particular) are |
pasky | 0:9858347c382d | 19 | * heavy on many tiny memory allocations, which can get very troublesome |
pasky | 0:9858347c382d | 20 | * with mbed's malloc() - we get very high memory fragmentation. In many |
pasky | 0:9858347c382d | 21 | * cases, working with raw JSON is just fine, and in our demo example, |
pasky | 0:9858347c382d | 22 | * we still show picojson usage for end-user parsing of complex incoming |
pasky | 0:9858347c382d | 23 | * messages. */ |
pasky | 0:9858347c382d | 24 | |
embeddedartists | 7:55eb53c78b47 | 25 | #include "rtos.h" |
embeddedartists | 7:55eb53c78b47 | 26 | |
embeddedartists | 7:55eb53c78b47 | 27 | void pnub_err_handler(PubNubRes code, int line); |
embeddedartists | 7:55eb53c78b47 | 28 | extern Serial pc; |
embeddedartists | 7:55eb53c78b47 | 29 | extern Mutex stdio_mutex; |
embeddedartists | 7:55eb53c78b47 | 30 | #define safe_printf(...) do { \ |
embeddedartists | 7:55eb53c78b47 | 31 | stdio_mutex.lock(); \ |
embeddedartists | 7:55eb53c78b47 | 32 | pc.printf(__VA_ARGS__); \ |
embeddedartists | 7:55eb53c78b47 | 33 | stdio_mutex.unlock(); \ |
embeddedartists | 7:55eb53c78b47 | 34 | } while(0) |
embeddedartists | 7:55eb53c78b47 | 35 | |
embeddedartists | 7:55eb53c78b47 | 36 | #define PNUB_RETURN_STAT(__stat) do { \ |
embeddedartists | 7:55eb53c78b47 | 37 | if ((__stat) != PNR_OK) { \ |
embeddedartists | 7:55eb53c78b47 | 38 | pnub_err_handler((__stat), __LINE__); \ |
embeddedartists | 7:55eb53c78b47 | 39 | } \ |
embeddedartists | 7:55eb53c78b47 | 40 | return (__stat); \ |
embeddedartists | 7:55eb53c78b47 | 41 | } while(0) |
embeddedartists | 7:55eb53c78b47 | 42 | |
pasky | 0:9858347c382d | 43 | |
pasky | 0:9858347c382d | 44 | /** Custom no-frills HTTP stream. */ |
pasky | 0:9858347c382d | 45 | |
pasky | 0:9858347c382d | 46 | class PubNubHTTP: public TCPSocketConnection { |
pasky | 0:9858347c382d | 47 | public: |
pasky | 0:9858347c382d | 48 | /* Connect http socket to origin. */ |
pasky | 0:9858347c382d | 49 | PubNubRes http_connect(const char *hostname); |
pasky | 0:9858347c382d | 50 | |
pasky | 0:9858347c382d | 51 | /* These methods are used to send the request type and URL. */ |
pasky | 0:9858347c382d | 52 | /* Send a given NUL-terminated string over the http socket. */ |
pasky | 0:9858347c382d | 53 | void sendstr(const char *string); |
pasky | 0:9858347c382d | 54 | /* Send a given NUL-terminated string over the http socket, URL encoded. */ |
pasky | 0:9858347c382d | 55 | void sendstr_urlenc(const char *string); |
embeddedartists | 7:55eb53c78b47 | 56 | /* URL encode a given NUL-terminated string into the given buffer. */ |
embeddedartists | 7:55eb53c78b47 | 57 | void prepare_urlenc(const char *string, char* buff); |
pasky | 0:9858347c382d | 58 | |
pasky | 0:9858347c382d | 59 | /* A common HTTP request "bottom half" - send the rest of headers |
pasky | 0:9858347c382d | 60 | * and wait for reply + receive. */ |
pasky | 0:9858347c382d | 61 | PubNubRes http_request_bh(const char *host, char **reply, int *replylen); |
pasky | 0:9858347c382d | 62 | |
pasky | 0:9858347c382d | 63 | protected: |
pasky | 0:9858347c382d | 64 | /* These methods represent sub-stages of http_request_bh(). |
pasky | 0:9858347c382d | 65 | * They share the state of m_replybuf and m_replylen. */ |
pasky | 0:9858347c382d | 66 | PubNubRes http_send_headers(const char *host); |
pasky | 0:9858347c382d | 67 | PubNubRes http_recv_headers(); |
pasky | 0:9858347c382d | 68 | PubNubRes http_recv_content(); |
pasky | 0:9858347c382d | 69 | |
pasky | 0:9858347c382d | 70 | char *m_replybuf; |
pasky | 0:9858347c382d | 71 | int m_replylen; |
pasky | 0:9858347c382d | 72 | int m_content_length; |
pasky | 0:9858347c382d | 73 | }; |
pasky | 0:9858347c382d | 74 | |
pasky | 0:9858347c382d | 75 | PubNubRes |
pasky | 0:9858347c382d | 76 | PubNubHTTP::http_connect(const char *hostname) |
pasky | 0:9858347c382d | 77 | { |
pasky | 0:9858347c382d | 78 | int ret = connect(hostname, 80); |
pasky | 0:9858347c382d | 79 | if (ret < 0) { |
pasky | 0:9858347c382d | 80 | close(); |
embeddedartists | 7:55eb53c78b47 | 81 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 82 | safe_printf("http_connect(%s): ret = %d\n", hostname, ret); |
embeddedartists | 7:55eb53c78b47 | 83 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 84 | } |
pasky | 0:9858347c382d | 85 | return PNR_OK; |
pasky | 0:9858347c382d | 86 | } |
pasky | 0:9858347c382d | 87 | |
pasky | 0:9858347c382d | 88 | void |
pasky | 0:9858347c382d | 89 | PubNubHTTP::sendstr(const char *s) |
pasky | 0:9858347c382d | 90 | { |
pasky | 0:9858347c382d | 91 | send_all((char *) s, strlen(s)); |
pasky | 0:9858347c382d | 92 | } |
pasky | 0:9858347c382d | 93 | |
pasky | 0:9858347c382d | 94 | void |
pasky | 0:9858347c382d | 95 | PubNubHTTP::sendstr_urlenc(const char *s) |
pasky | 0:9858347c382d | 96 | { |
pasky | 0:9858347c382d | 97 | while (s[0]) { |
pasky | 0:9858347c382d | 98 | /* RFC 3986 Unreserved characters plus few |
pasky | 0:9858347c382d | 99 | * safe reserved ones. */ |
pasky | 0:9858347c382d | 100 | size_t okspan = strspn(s, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~" ",=:;@[]"); |
pasky | 0:9858347c382d | 101 | if (okspan > 0) { |
pasky | 0:9858347c382d | 102 | send_all((char *) s, okspan); |
pasky | 0:9858347c382d | 103 | s += okspan; |
pasky | 0:9858347c382d | 104 | } |
pasky | 0:9858347c382d | 105 | if (s[0]) { |
pasky | 0:9858347c382d | 106 | /* %-encode a non-ok character. */ |
pasky | 0:9858347c382d | 107 | char enc[3] = {'%'}; |
pasky | 0:9858347c382d | 108 | enc[1] = "0123456789ABCDEF"[s[0] / 16]; |
pasky | 0:9858347c382d | 109 | enc[2] = "0123456789ABCDEF"[s[0] % 16]; |
pasky | 0:9858347c382d | 110 | send_all((char *) enc, 3); |
pasky | 0:9858347c382d | 111 | s++; |
pasky | 0:9858347c382d | 112 | } |
pasky | 0:9858347c382d | 113 | } |
pasky | 0:9858347c382d | 114 | } |
pasky | 0:9858347c382d | 115 | |
embeddedartists | 7:55eb53c78b47 | 116 | void |
embeddedartists | 7:55eb53c78b47 | 117 | PubNubHTTP::prepare_urlenc(const char *s, char* buff) |
embeddedartists | 7:55eb53c78b47 | 118 | { |
embeddedartists | 7:55eb53c78b47 | 119 | char* b = buff; |
embeddedartists | 7:55eb53c78b47 | 120 | while (s[0]) { |
embeddedartists | 7:55eb53c78b47 | 121 | /* RFC 3986 Unreserved characters plus few |
embeddedartists | 7:55eb53c78b47 | 122 | * safe reserved ones. */ |
embeddedartists | 7:55eb53c78b47 | 123 | size_t okspan = strspn(s, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~" ",=:;@[]"); |
embeddedartists | 7:55eb53c78b47 | 124 | if (okspan > 0) { |
embeddedartists | 7:55eb53c78b47 | 125 | strncpy(b, s, okspan); |
embeddedartists | 7:55eb53c78b47 | 126 | b += okspan; |
embeddedartists | 7:55eb53c78b47 | 127 | //send_all((char *) s, okspan); |
embeddedartists | 7:55eb53c78b47 | 128 | s += okspan; |
embeddedartists | 7:55eb53c78b47 | 129 | } |
embeddedartists | 7:55eb53c78b47 | 130 | if (s[0]) { |
embeddedartists | 7:55eb53c78b47 | 131 | /* %-encode a non-ok character. */ |
embeddedartists | 7:55eb53c78b47 | 132 | *b++ = '%'; |
embeddedartists | 7:55eb53c78b47 | 133 | *b++ = "0123456789ABCDEF"[s[0] / 16]; |
embeddedartists | 7:55eb53c78b47 | 134 | *b++ = "0123456789ABCDEF"[s[0] % 16]; |
embeddedartists | 7:55eb53c78b47 | 135 | //send_all((char *) enc, 3); |
embeddedartists | 7:55eb53c78b47 | 136 | s++; |
embeddedartists | 7:55eb53c78b47 | 137 | } |
embeddedartists | 7:55eb53c78b47 | 138 | } |
embeddedartists | 7:55eb53c78b47 | 139 | *b = '\0'; |
embeddedartists | 7:55eb53c78b47 | 140 | } |
embeddedartists | 7:55eb53c78b47 | 141 | |
pasky | 0:9858347c382d | 142 | PubNubRes |
pasky | 0:9858347c382d | 143 | PubNubHTTP::http_request_bh(const char *host, char **reply, int *replylen) |
pasky | 0:9858347c382d | 144 | { |
pasky | 0:9858347c382d | 145 | m_replybuf = NULL; |
pasky | 0:9858347c382d | 146 | m_replylen = 0; |
pasky | 0:9858347c382d | 147 | |
pasky | 0:9858347c382d | 148 | PubNubRes res; |
pasky | 0:9858347c382d | 149 | res = http_send_headers(host); |
pasky | 0:9858347c382d | 150 | if (res != PNR_OK) { |
pasky | 0:9858347c382d | 151 | close(); |
embeddedartists | 7:55eb53c78b47 | 152 | //return res; |
embeddedartists | 7:55eb53c78b47 | 153 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 154 | } |
pasky | 0:9858347c382d | 155 | |
pasky | 0:9858347c382d | 156 | res = http_recv_headers(); |
pasky | 0:9858347c382d | 157 | if (res != PNR_OK) { |
pasky | 0:9858347c382d | 158 | if (m_replybuf) free(m_replybuf); |
pasky | 0:9858347c382d | 159 | close(); |
embeddedartists | 7:55eb53c78b47 | 160 | //return res; |
embeddedartists | 7:55eb53c78b47 | 161 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 162 | } |
pasky | 0:9858347c382d | 163 | |
pasky | 0:9858347c382d | 164 | res = http_recv_content(); |
pasky | 0:9858347c382d | 165 | if (res != PNR_OK) { |
pasky | 0:9858347c382d | 166 | if (m_replybuf) free(m_replybuf); |
pasky | 0:9858347c382d | 167 | close(); |
embeddedartists | 7:55eb53c78b47 | 168 | //return res; |
embeddedartists | 7:55eb53c78b47 | 169 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 170 | } |
pasky | 0:9858347c382d | 171 | |
pasky | 0:9858347c382d | 172 | close(); |
pasky | 0:9858347c382d | 173 | *reply = (char *) realloc(m_replybuf, m_replylen); |
pasky | 0:9858347c382d | 174 | *replylen = m_replylen; |
pasky | 0:9858347c382d | 175 | return PNR_OK; |
pasky | 0:9858347c382d | 176 | } |
pasky | 0:9858347c382d | 177 | |
pasky | 0:9858347c382d | 178 | PubNubRes |
pasky | 0:9858347c382d | 179 | PubNubHTTP::http_send_headers(const char *host) |
pasky | 0:9858347c382d | 180 | { |
embeddedartists | 7:55eb53c78b47 | 181 | #ifdef USE_ORIGINAL_CODE |
pasky | 0:9858347c382d | 182 | /* Finish the first line of the request. */ |
pasky | 0:9858347c382d | 183 | sendstr(" HTTP/1.1\r\n"); |
pasky | 0:9858347c382d | 184 | /* Finish HTTP request. */ |
pasky | 0:9858347c382d | 185 | sendstr("Host: "); |
pasky | 0:9858347c382d | 186 | sendstr(host); |
pasky | 0:9858347c382d | 187 | sendstr("\r\nUser-Agent: PubNub-mbed/0.1\r\nConnection: close\r\n\r\n"); |
pasky | 0:9858347c382d | 188 | if (!is_connected()) |
embeddedartists | 7:55eb53c78b47 | 189 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 190 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 191 | return PNR_OK; |
embeddedartists | 7:55eb53c78b47 | 192 | #else |
embeddedartists | 7:55eb53c78b47 | 193 | char buff[200]; |
embeddedartists | 7:55eb53c78b47 | 194 | snprintf(buff, 200, " HTTP/1.1\r\nHost: %s\r\nUser-Agent: PubNub-mbed/0.1\r\nConnection: close\r\n\r\n", host); |
embeddedartists | 7:55eb53c78b47 | 195 | sendstr(buff); |
embeddedartists | 7:55eb53c78b47 | 196 | if (!is_connected()) |
embeddedartists | 7:55eb53c78b47 | 197 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 198 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
embeddedartists | 7:55eb53c78b47 | 199 | return PNR_OK; |
embeddedartists | 7:55eb53c78b47 | 200 | #endif |
pasky | 0:9858347c382d | 201 | } |
pasky | 0:9858347c382d | 202 | |
pasky | 0:9858347c382d | 203 | PubNubRes |
pasky | 0:9858347c382d | 204 | PubNubHTTP::http_recv_headers() |
pasky | 0:9858347c382d | 205 | { |
pasky | 0:9858347c382d | 206 | /* Now, read HTTP reply. */ |
pasky | 0:9858347c382d | 207 | m_replybuf = (char *) malloc(PUBNUB_REPLY_MAXLEN+1); |
pasky | 0:9858347c382d | 208 | |
pasky | 0:9858347c382d | 209 | /* First, receive headers. */ |
pasky | 0:9858347c382d | 210 | /* XXX: For now, we assume complete headers will fit in m_replybuf. */ |
pasky | 0:9858347c382d | 211 | m_replylen = receive_all(m_replybuf, PUBNUB_REPLY_MAXLEN); |
pasky | 0:9858347c382d | 212 | if (m_replylen < 0) |
embeddedartists | 7:55eb53c78b47 | 213 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 214 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 215 | m_replybuf[m_replylen] = 0; |
pasky | 0:9858347c382d | 216 | |
pasky | 0:9858347c382d | 217 | char *bufptr = m_replybuf; |
pasky | 0:9858347c382d | 218 | |
pasky | 0:9858347c382d | 219 | /* Parse the first line. */ |
pasky | 0:9858347c382d | 220 | if (strncmp(bufptr, "HTTP/1.", 7) || !bufptr[7] || !bufptr[8]) |
embeddedartists | 7:55eb53c78b47 | 221 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 222 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 223 | int http_code = atoi(bufptr+9); |
pasky | 0:9858347c382d | 224 | if (http_code / 100 != 2) |
embeddedartists | 7:55eb53c78b47 | 225 | //return PNR_HTTP_ERROR; |
embeddedartists | 7:55eb53c78b47 | 226 | PNUB_RETURN_STAT(PNR_HTTP_ERROR); |
pasky | 0:9858347c382d | 227 | bufptr = strstr(bufptr, "\r\n"); |
pasky | 0:9858347c382d | 228 | if (!bufptr) |
embeddedartists | 7:55eb53c78b47 | 229 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 230 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 231 | bufptr += 2; |
pasky | 0:9858347c382d | 232 | |
pasky | 0:9858347c382d | 233 | /* Parse the rest of the lines. */ |
pasky | 0:9858347c382d | 234 | m_content_length = 0; |
pasky | 0:9858347c382d | 235 | bool is_chunked = false; |
pasky | 0:9858347c382d | 236 | char *newline; |
pasky | 0:9858347c382d | 237 | for (;; bufptr = newline+2) { |
pasky | 0:9858347c382d | 238 | newline = strstr(bufptr, "\r\n"); |
pasky | 0:9858347c382d | 239 | if (!newline) |
embeddedartists | 7:55eb53c78b47 | 240 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 241 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 242 | *newline = 0; |
pasky | 0:9858347c382d | 243 | |
pasky | 0:9858347c382d | 244 | char h_chunked[] = "Transfer-Encoding: chunked"; |
pasky | 0:9858347c382d | 245 | char h_length[] = "Content-Length: "; |
pasky | 0:9858347c382d | 246 | if (*bufptr == 0) { |
pasky | 0:9858347c382d | 247 | /* Empty line. End of headers. */ |
pasky | 0:9858347c382d | 248 | bufptr += 2; |
pasky | 0:9858347c382d | 249 | break; |
pasky | 0:9858347c382d | 250 | } else if (!strncmp(bufptr, h_chunked, sizeof(h_chunked)-1)) { |
pasky | 0:9858347c382d | 251 | /* Transfer-Encoding: chunked */ |
pasky | 0:9858347c382d | 252 | is_chunked = true; |
pasky | 0:9858347c382d | 253 | } else if (!strncmp(bufptr, h_length, sizeof(h_length)-1)) { |
pasky | 0:9858347c382d | 254 | /* Content-Length: ... */ |
pasky | 0:9858347c382d | 255 | m_content_length = atoi(bufptr + sizeof(h_length)-1); |
pasky | 0:9858347c382d | 256 | } |
pasky | 0:9858347c382d | 257 | } |
pasky | 0:9858347c382d | 258 | |
pasky | 0:9858347c382d | 259 | /* Possibly process a chunk header. */ |
pasky | 0:9858347c382d | 260 | if (is_chunked) { |
pasky | 0:9858347c382d | 261 | m_content_length = atoi(bufptr); |
pasky | 0:9858347c382d | 262 | bufptr = strstr(bufptr, "\r\n"); |
pasky | 0:9858347c382d | 263 | if (!bufptr) |
embeddedartists | 7:55eb53c78b47 | 264 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 265 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 266 | bufptr += 2; |
pasky | 0:9858347c382d | 267 | } |
pasky | 0:9858347c382d | 268 | |
pasky | 0:9858347c382d | 269 | /* Consolidate the buffer. */ |
pasky | 0:9858347c382d | 270 | m_replylen -= bufptr - m_replybuf; |
pasky | 0:9858347c382d | 271 | memmove(m_replybuf, bufptr, m_replylen); |
pasky | 0:9858347c382d | 272 | |
pasky | 0:9858347c382d | 273 | return PNR_OK; |
pasky | 0:9858347c382d | 274 | } |
pasky | 0:9858347c382d | 275 | |
pasky | 0:9858347c382d | 276 | PubNubRes |
pasky | 0:9858347c382d | 277 | PubNubHTTP::http_recv_content() |
pasky | 0:9858347c382d | 278 | { |
pasky | 0:9858347c382d | 279 | /* Now, we are ready to process data! */ |
pasky | 0:9858347c382d | 280 | |
pasky | 0:9858347c382d | 281 | if (m_content_length > PUBNUB_REPLY_MAXLEN) { |
pasky | 0:9858347c382d | 282 | /* XXX: Actually, too much data, sorry. */ |
pasky | 0:9858347c382d | 283 | DBG printf("too much data\r\n"); |
embeddedartists | 7:55eb53c78b47 | 284 | //return PNR_FORMAT_ERROR; |
embeddedartists | 7:55eb53c78b47 | 285 | PNUB_RETURN_STAT(PNR_FORMAT_ERROR); |
pasky | 0:9858347c382d | 286 | } |
pasky | 0:9858347c382d | 287 | |
pasky | 0:9858347c382d | 288 | if (m_replylen < m_content_length) { |
pasky | 0:9858347c382d | 289 | /* More data coming. */ |
pasky | 0:9858347c382d | 290 | int recv2len = receive_all(m_replybuf + m_replylen, PUBNUB_REPLY_MAXLEN - m_replylen); |
pasky | 0:9858347c382d | 291 | if (recv2len < 0) |
embeddedartists | 7:55eb53c78b47 | 292 | //return PNR_IO_ERROR; |
embeddedartists | 7:55eb53c78b47 | 293 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 294 | m_replylen += recv2len; |
pasky | 0:9858347c382d | 295 | } |
pasky | 0:9858347c382d | 296 | |
pasky | 0:9858347c382d | 297 | if (m_replylen < m_content_length) |
embeddedartists | 7:55eb53c78b47 | 298 | //return PNR_IO_ERROR; /* Incomplete data. */ |
embeddedartists | 7:55eb53c78b47 | 299 | PNUB_RETURN_STAT(PNR_IO_ERROR); |
pasky | 0:9858347c382d | 300 | return PNR_OK; |
pasky | 0:9858347c382d | 301 | } |
pasky | 0:9858347c382d | 302 | |
pasky | 0:9858347c382d | 303 | |
pasky | 0:9858347c382d | 304 | /** Some utility routines. */ |
pasky | 0:9858347c382d | 305 | |
pasky | 0:9858347c382d | 306 | /* Split a JSON array (with arbitrary contents) to multiple NUL-terminated |
pasky | 0:9858347c382d | 307 | * C strings. */ |
pasky | 0:9858347c382d | 308 | static PubNubRes |
pasky | 0:9858347c382d | 309 | split_array(char *buf, int len) |
pasky | 0:9858347c382d | 310 | { |
pasky | 0:9858347c382d | 311 | bool escaped = false, in_string = false; |
pasky | 0:9858347c382d | 312 | int bracket_level = 0; |
pasky | 0:9858347c382d | 313 | for (int i = 0; i < len; i++) { |
pasky | 0:9858347c382d | 314 | if (escaped) { |
pasky | 0:9858347c382d | 315 | escaped = false; |
pasky | 0:9858347c382d | 316 | } else if (in_string) { |
pasky | 0:9858347c382d | 317 | switch (buf[i]) { |
pasky | 0:9858347c382d | 318 | case '\\': escaped = true; break; |
pasky | 0:9858347c382d | 319 | case '"': in_string = false; break; |
pasky | 0:9858347c382d | 320 | default: break; |
pasky | 0:9858347c382d | 321 | } |
pasky | 0:9858347c382d | 322 | } else { |
pasky | 0:9858347c382d | 323 | switch (buf[i]) { |
pasky | 0:9858347c382d | 324 | case '"': in_string = true; break; |
pasky | 0:9858347c382d | 325 | case '[': case '{': bracket_level++; break; |
pasky | 0:9858347c382d | 326 | case ']': case '}': bracket_level--; break; |
pasky | 0:9858347c382d | 327 | /* if at root, split! */ |
pasky | 0:9858347c382d | 328 | case ',': if (bracket_level == 0) buf[i] = 0; break; |
pasky | 0:9858347c382d | 329 | default: break; |
pasky | 0:9858347c382d | 330 | } |
pasky | 0:9858347c382d | 331 | } |
pasky | 0:9858347c382d | 332 | } |
pasky | 0:9858347c382d | 333 | DBG printf("parse %d %d %d\r\n", escaped, in_string, bracket_level); |
pasky | 0:9858347c382d | 334 | if (escaped || in_string || bracket_level > 0) |
embeddedartists | 7:55eb53c78b47 | 335 | //return PNR_FORMAT_ERROR; |
embeddedartists | 7:55eb53c78b47 | 336 | PNUB_RETURN_STAT(PNR_FORMAT_ERROR); |
pasky | 0:9858347c382d | 337 | return PNR_OK; |
pasky | 0:9858347c382d | 338 | } |
pasky | 0:9858347c382d | 339 | |
pasky | 0:9858347c382d | 340 | |
pasky | 0:9858347c382d | 341 | /** PubNub API. */ |
pasky | 0:9858347c382d | 342 | |
pasky | 0:9858347c382d | 343 | PubNub::PubNub(const char *publish_key_, const char *subscribe_key_, const char *origin_) : |
pasky | 0:9858347c382d | 344 | m_publish_key(publish_key_), m_subscribe_key(subscribe_key_), m_origin(origin_), |
pasky | 0:9858347c382d | 345 | m_replybuf(NULL), m_replylen(0) |
pasky | 0:9858347c382d | 346 | { |
pasky | 0:9858347c382d | 347 | strcpy(m_timetoken, "0"); |
pasky | 0:9858347c382d | 348 | } |
pasky | 0:9858347c382d | 349 | |
pasky | 0:9858347c382d | 350 | PubNub::~PubNub() |
pasky | 0:9858347c382d | 351 | { |
pasky | 0:9858347c382d | 352 | if (m_replybuf) |
pasky | 0:9858347c382d | 353 | free(m_replybuf); |
pasky | 0:9858347c382d | 354 | } |
pasky | 0:9858347c382d | 355 | |
pasky | 0:9858347c382d | 356 | const char * |
pasky | 0:9858347c382d | 357 | PubNub::origin_hostname() |
pasky | 0:9858347c382d | 358 | { |
pasky | 0:9858347c382d | 359 | /* TODO: More generic URL handling */ |
pasky | 0:9858347c382d | 360 | return m_origin + strlen("http://"); |
pasky | 0:9858347c382d | 361 | } |
pasky | 0:9858347c382d | 362 | |
pasky | 0:9858347c382d | 363 | |
pasky | 0:9858347c382d | 364 | PubNubRes |
pasky | 0:9858347c382d | 365 | PubNub::publish(const char *channel, const char *message, char **reply) |
pasky | 0:9858347c382d | 366 | { |
pasky | 0:9858347c382d | 367 | PubNubHTTP http; |
pasky | 0:9858347c382d | 368 | PubNubRes res = http.http_connect(origin_hostname()); |
pasky | 0:9858347c382d | 369 | if (res != PNR_OK) |
embeddedartists | 7:55eb53c78b47 | 370 | //return res; |
embeddedartists | 7:55eb53c78b47 | 371 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 372 | |
embeddedartists | 7:55eb53c78b47 | 373 | #ifdef USE_ORIGINAL_CODE |
pasky | 0:9858347c382d | 374 | http.sendstr("GET /publish/"); |
pasky | 0:9858347c382d | 375 | http.sendstr(m_publish_key); |
pasky | 0:9858347c382d | 376 | http.sendstr("/"); |
pasky | 0:9858347c382d | 377 | http.sendstr(m_subscribe_key); |
pasky | 0:9858347c382d | 378 | http.sendstr("/0/"); |
pasky | 0:9858347c382d | 379 | http.sendstr(channel); |
pasky | 0:9858347c382d | 380 | http.sendstr("/0/"); |
pasky | 0:9858347c382d | 381 | http.sendstr_urlenc(message); |
embeddedartists | 7:55eb53c78b47 | 382 | #else |
embeddedartists | 7:55eb53c78b47 | 383 | char* buff = (char*)malloc(2000); |
embeddedartists | 7:55eb53c78b47 | 384 | int len = sprintf(buff, "GET /publish/%s/%s/0/%s/0/",m_publish_key,m_subscribe_key,channel); |
embeddedartists | 7:55eb53c78b47 | 385 | http.prepare_urlenc(message, buff+len); |
embeddedartists | 7:55eb53c78b47 | 386 | http.sendstr(buff); |
embeddedartists | 7:55eb53c78b47 | 387 | free(buff); |
embeddedartists | 7:55eb53c78b47 | 388 | #endif |
pasky | 0:9858347c382d | 389 | |
pasky | 0:9858347c382d | 390 | char *locreply; |
pasky | 0:9858347c382d | 391 | if (!reply) |
pasky | 0:9858347c382d | 392 | reply = &locreply; |
pasky | 0:9858347c382d | 393 | int replylen; |
pasky | 0:9858347c382d | 394 | |
pasky | 0:9858347c382d | 395 | res = http.http_request_bh(origin_hostname(), reply, &replylen); |
pasky | 0:9858347c382d | 396 | if (res != PNR_OK) |
embeddedartists | 7:55eb53c78b47 | 397 | //return res; |
embeddedartists | 7:55eb53c78b47 | 398 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 399 | bool success = (*reply)[1] == '1' && (*reply)[2] == ','; |
pasky | 0:9858347c382d | 400 | if (reply == &locreply) |
pasky | 0:9858347c382d | 401 | free(locreply); |
embeddedartists | 7:55eb53c78b47 | 402 | //return success ? PNR_OK : PNR_PUBNUB_ERROR; |
embeddedartists | 7:55eb53c78b47 | 403 | PNUB_RETURN_STAT(success ? PNR_OK : PNR_PUBNUB_ERROR); |
pasky | 0:9858347c382d | 404 | } |
pasky | 0:9858347c382d | 405 | |
embeddedartists | 7:55eb53c78b47 | 406 | PubNubRes |
embeddedartists | 7:55eb53c78b47 | 407 | PubNub::publish_urlenc(const char *channel, const char *message, char **reply) |
embeddedartists | 7:55eb53c78b47 | 408 | { |
embeddedartists | 7:55eb53c78b47 | 409 | PubNubHTTP http; |
embeddedartists | 7:55eb53c78b47 | 410 | PubNubRes res = http.http_connect(origin_hostname()); |
embeddedartists | 7:55eb53c78b47 | 411 | if (res != PNR_OK) |
embeddedartists | 7:55eb53c78b47 | 412 | //return res; |
embeddedartists | 7:55eb53c78b47 | 413 | PNUB_RETURN_STAT(res); |
embeddedartists | 7:55eb53c78b47 | 414 | |
embeddedartists | 7:55eb53c78b47 | 415 | #ifdef USE_ORIGINAL_CODE |
embeddedartists | 7:55eb53c78b47 | 416 | http.sendstr("GET /publish/"); |
embeddedartists | 7:55eb53c78b47 | 417 | http.sendstr(m_publish_key); |
embeddedartists | 7:55eb53c78b47 | 418 | http.sendstr("/"); |
embeddedartists | 7:55eb53c78b47 | 419 | http.sendstr(m_subscribe_key); |
embeddedartists | 7:55eb53c78b47 | 420 | http.sendstr("/0/"); |
embeddedartists | 7:55eb53c78b47 | 421 | http.sendstr(channel); |
embeddedartists | 7:55eb53c78b47 | 422 | http.sendstr("/0/"); |
embeddedartists | 7:55eb53c78b47 | 423 | http.sendstr_urlenc(message); |
embeddedartists | 7:55eb53c78b47 | 424 | #else |
embeddedartists | 7:55eb53c78b47 | 425 | char* buff = (char*)malloc(2000); |
embeddedartists | 7:55eb53c78b47 | 426 | /*int len = */sprintf(buff, "GET /publish/%s/%s/0/%s/0/%s",m_publish_key,m_subscribe_key,channel,message); |
embeddedartists | 7:55eb53c78b47 | 427 | //http.prepare_urlenc(message, buff+len); |
embeddedartists | 7:55eb53c78b47 | 428 | http.sendstr(buff); |
embeddedartists | 7:55eb53c78b47 | 429 | free(buff); |
embeddedartists | 7:55eb53c78b47 | 430 | #endif |
embeddedartists | 7:55eb53c78b47 | 431 | |
embeddedartists | 7:55eb53c78b47 | 432 | char *locreply; |
embeddedartists | 7:55eb53c78b47 | 433 | if (!reply) |
embeddedartists | 7:55eb53c78b47 | 434 | reply = &locreply; |
embeddedartists | 7:55eb53c78b47 | 435 | int replylen; |
embeddedartists | 7:55eb53c78b47 | 436 | |
embeddedartists | 7:55eb53c78b47 | 437 | res = http.http_request_bh(origin_hostname(), reply, &replylen); |
embeddedartists | 7:55eb53c78b47 | 438 | if (res != PNR_OK) |
embeddedartists | 7:55eb53c78b47 | 439 | //return res; |
embeddedartists | 7:55eb53c78b47 | 440 | PNUB_RETURN_STAT(res); |
embeddedartists | 7:55eb53c78b47 | 441 | bool success = (*reply)[1] == '1' && (*reply)[2] == ','; |
embeddedartists | 7:55eb53c78b47 | 442 | if (reply == &locreply) |
embeddedartists | 7:55eb53c78b47 | 443 | free(locreply); |
embeddedartists | 7:55eb53c78b47 | 444 | //return success ? PNR_OK : PNR_PUBNUB_ERROR; |
embeddedartists | 7:55eb53c78b47 | 445 | PNUB_RETURN_STAT(success ? PNR_OK : PNR_PUBNUB_ERROR); |
embeddedartists | 7:55eb53c78b47 | 446 | } |
pasky | 0:9858347c382d | 447 | |
pasky | 0:9858347c382d | 448 | PubNubRes |
pasky | 0:9858347c382d | 449 | PubNub::subscribe(const char *channel, char **reply) |
pasky | 0:9858347c382d | 450 | { |
pasky | 0:9858347c382d | 451 | if (m_replybuf) { |
pasky | 0:9858347c382d | 452 | int prevlen = strlen(m_replybuf); |
pasky | 0:9858347c382d | 453 | //DBG printf("reply (%s) %d > %d: %d\r\n", m_replybuf, prevlen, m_replylen); |
pasky | 0:9858347c382d | 454 | if (prevlen < m_replylen) { |
pasky | 0:9858347c382d | 455 | /* Next message from stash-away buffer. */ |
pasky | 0:9858347c382d | 456 | /* XXX: We can be either memory-frugal or CPU-frugal |
pasky | 0:9858347c382d | 457 | * here. We choose to be memory-frugal by copying |
pasky | 0:9858347c382d | 458 | * over messages many times, but we may want to make |
pasky | 0:9858347c382d | 459 | * this configurable. */ |
pasky | 0:9858347c382d | 460 | m_replylen -= prevlen + 1; |
pasky | 0:9858347c382d | 461 | memmove(m_replybuf, m_replybuf + prevlen + 1, m_replylen); |
pasky | 0:9858347c382d | 462 | m_replybuf = (char *) realloc(m_replybuf, m_replylen); |
pasky | 0:9858347c382d | 463 | *reply = m_replybuf; |
pasky | 0:9858347c382d | 464 | return PNR_OK; |
pasky | 0:9858347c382d | 465 | |
pasky | 0:9858347c382d | 466 | } else { |
pasky | 0:9858347c382d | 467 | /* That's all. free() and fetch new messages. */ |
pasky | 0:9858347c382d | 468 | free(m_replybuf); |
pasky | 0:9858347c382d | 469 | m_replybuf = NULL; |
pasky | 0:9858347c382d | 470 | m_replylen = 0; |
pasky | 0:9858347c382d | 471 | } |
pasky | 0:9858347c382d | 472 | } |
pasky | 0:9858347c382d | 473 | |
pasky | 0:9858347c382d | 474 | PubNubHTTP http; |
pasky | 0:9858347c382d | 475 | PubNubRes res; |
pasky | 0:9858347c382d | 476 | res = http.http_connect(origin_hostname()); |
pasky | 0:9858347c382d | 477 | if (res != PNR_OK) |
embeddedartists | 7:55eb53c78b47 | 478 | //return res; |
embeddedartists | 7:55eb53c78b47 | 479 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 480 | |
embeddedartists | 7:55eb53c78b47 | 481 | #ifdef USE_ORIGINAL_CODE |
pasky | 0:9858347c382d | 482 | http.sendstr("GET /subscribe/"); |
pasky | 0:9858347c382d | 483 | http.sendstr(m_subscribe_key); |
pasky | 0:9858347c382d | 484 | http.sendstr("/"); |
pasky | 0:9858347c382d | 485 | http.sendstr(channel); |
pasky | 0:9858347c382d | 486 | http.sendstr("/0/"); |
pasky | 0:9858347c382d | 487 | http.sendstr(m_timetoken); |
embeddedartists | 7:55eb53c78b47 | 488 | #else |
embeddedartists | 7:55eb53c78b47 | 489 | char buff[200]; |
embeddedartists | 7:55eb53c78b47 | 490 | snprintf(buff, 200, "GET /subscribe/%s/%s/0/%s", m_subscribe_key, channel, m_timetoken); |
embeddedartists | 7:55eb53c78b47 | 491 | http.sendstr(buff); |
embeddedartists | 7:55eb53c78b47 | 492 | #endif |
pasky | 0:9858347c382d | 493 | |
pasky | 0:9858347c382d | 494 | char *replybuf = NULL; |
pasky | 0:9858347c382d | 495 | int replylen; |
pasky | 0:9858347c382d | 496 | res = http.http_request_bh(origin_hostname(), &replybuf, &replylen); |
pasky | 0:9858347c382d | 497 | if (res != PNR_OK) |
pasky | 0:9858347c382d | 498 | goto error; |
pasky | 0:9858347c382d | 499 | |
pasky | 0:9858347c382d | 500 | /* Process the reply, sets timetoken and m_replybuf, m_replylen. */ |
pasky | 0:9858347c382d | 501 | res = subscribe_processjson(replybuf, replylen); |
pasky | 0:9858347c382d | 502 | if (res != PNR_OK) |
pasky | 0:9858347c382d | 503 | goto error; |
pasky | 0:9858347c382d | 504 | replybuf = NULL; // freed by processjosn |
pasky | 0:9858347c382d | 505 | |
pasky | 0:9858347c382d | 506 | /* Split JSON array to messages. */ |
pasky | 0:9858347c382d | 507 | res = split_array(m_replybuf, m_replylen); |
pasky | 0:9858347c382d | 508 | if (res != PNR_OK) { |
pasky | 0:9858347c382d | 509 | free(m_replybuf); |
pasky | 0:9858347c382d | 510 | goto error; |
pasky | 0:9858347c382d | 511 | } |
pasky | 0:9858347c382d | 512 | |
pasky | 0:9858347c382d | 513 | *reply = m_replybuf; |
pasky | 0:9858347c382d | 514 | return res; |
pasky | 0:9858347c382d | 515 | |
pasky | 0:9858347c382d | 516 | error: |
pasky | 0:9858347c382d | 517 | if (res == PNR_FORMAT_ERROR) { |
pasky | 0:9858347c382d | 518 | /* In case of PubNub protocol error, abort an ongoing |
pasky | 0:9858347c382d | 519 | * subscribe and start over. This means some messages |
pasky | 0:9858347c382d | 520 | * were lost, but allows us to recover from bad |
pasky | 0:9858347c382d | 521 | * situations, e.g. too many messages queued or |
pasky | 0:9858347c382d | 522 | * unexpected problem caused by a particular message. */ |
pasky | 0:9858347c382d | 523 | strcpy(m_timetoken, "0"); |
pasky | 0:9858347c382d | 524 | } |
pasky | 0:9858347c382d | 525 | if (reply) |
pasky | 0:9858347c382d | 526 | free(reply); |
pasky | 0:9858347c382d | 527 | m_replybuf = NULL; |
pasky | 0:9858347c382d | 528 | m_replylen = 0; |
embeddedartists | 7:55eb53c78b47 | 529 | //return res; |
embeddedartists | 7:55eb53c78b47 | 530 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 531 | } |
pasky | 0:9858347c382d | 532 | |
pasky | 0:9858347c382d | 533 | PubNubRes |
pasky | 0:9858347c382d | 534 | PubNub::subscribe_processjson(char *reply, int replylen) |
pasky | 0:9858347c382d | 535 | { |
pasky | 0:9858347c382d | 536 | if (reply[0] != '[' || reply[replylen-1] != ']' |
pasky | 0:9858347c382d | 537 | || reply[replylen-2] != '"') { |
pasky | 0:9858347c382d | 538 | DBG printf("bad reply '%s'\r\n", reply); |
embeddedartists | 7:55eb53c78b47 | 539 | //return PNR_FORMAT_ERROR; |
embeddedartists | 7:55eb53c78b47 | 540 | PNUB_RETURN_STAT(PNR_FORMAT_ERROR); |
pasky | 0:9858347c382d | 541 | } |
pasky | 0:9858347c382d | 542 | |
pasky | 0:9858347c382d | 543 | /* Extract timetoken. */ |
pasky | 0:9858347c382d | 544 | reply[replylen-2] = 0; |
pasky | 0:9858347c382d | 545 | int i; |
pasky | 0:9858347c382d | 546 | for (i = replylen-3; i > 0 && i > int(replylen-3 - (sizeof(m_timetoken)-1)); i--) |
pasky | 0:9858347c382d | 547 | if (reply[i] == '"') |
pasky | 0:9858347c382d | 548 | break; |
pasky | 0:9858347c382d | 549 | if (!i || reply[i-1] != ',' || replylen-2 - (i+1) >= 64) { |
pasky | 0:9858347c382d | 550 | DBG printf("bad reply '%s'\r\n", reply); |
embeddedartists | 7:55eb53c78b47 | 551 | //return PNR_FORMAT_ERROR; |
embeddedartists | 7:55eb53c78b47 | 552 | PNUB_RETURN_STAT(PNR_FORMAT_ERROR); |
pasky | 0:9858347c382d | 553 | } |
pasky | 0:9858347c382d | 554 | strcpy(m_timetoken, &reply[i+1]); |
pasky | 0:9858347c382d | 555 | reply[i-1] = 0; // terminate the [] message array |
pasky | 0:9858347c382d | 556 | |
pasky | 0:9858347c382d | 557 | /* Empty reply? */ |
pasky | 0:9858347c382d | 558 | if (i == 4) { /* "[[]" */ |
pasky | 0:9858347c382d | 559 | free(reply); |
pasky | 0:9858347c382d | 560 | m_replybuf = NULL; |
pasky | 0:9858347c382d | 561 | m_replylen = 0; |
pasky | 0:9858347c382d | 562 | return PNR_OK; |
pasky | 0:9858347c382d | 563 | } |
pasky | 0:9858347c382d | 564 | |
pasky | 0:9858347c382d | 565 | /* Extract the messages array. */ |
pasky | 0:9858347c382d | 566 | if (reply[1] != '[' || reply[i-2] != ']') { |
pasky | 0:9858347c382d | 567 | DBG printf("bad reply end '%s'\r\n", reply); |
embeddedartists | 7:55eb53c78b47 | 568 | //return PNR_FORMAT_ERROR; |
embeddedartists | 7:55eb53c78b47 | 569 | PNUB_RETURN_STAT(PNR_FORMAT_ERROR); |
pasky | 0:9858347c382d | 570 | } |
pasky | 0:9858347c382d | 571 | reply[i-2] = 0; |
pasky | 0:9858347c382d | 572 | |
pasky | 0:9858347c382d | 573 | /* Shrink memory buffer to bare minimum. */ |
pasky | 0:9858347c382d | 574 | memmove(reply, reply + 2, i-2-2); |
pasky | 0:9858347c382d | 575 | m_replylen = i-2-2; |
pasky | 0:9858347c382d | 576 | m_replybuf = (char *) realloc(reply, m_replylen); |
pasky | 0:9858347c382d | 577 | |
pasky | 0:9858347c382d | 578 | return PNR_OK; |
pasky | 0:9858347c382d | 579 | } |
pasky | 0:9858347c382d | 580 | |
pasky | 0:9858347c382d | 581 | |
pasky | 0:9858347c382d | 582 | PubNubRes |
pasky | 0:9858347c382d | 583 | PubNub::history(const char *channel, char **reply, int *replysize, int limit) |
pasky | 0:9858347c382d | 584 | { |
pasky | 0:9858347c382d | 585 | PubNubHTTP http; |
pasky | 0:9858347c382d | 586 | PubNubRes res; |
pasky | 0:9858347c382d | 587 | res = http.http_connect(origin_hostname()); |
pasky | 0:9858347c382d | 588 | if (res != PNR_OK) |
embeddedartists | 7:55eb53c78b47 | 589 | //return res; |
embeddedartists | 7:55eb53c78b47 | 590 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 591 | |
embeddedartists | 7:55eb53c78b47 | 592 | #ifdef USE_ORIGINAL_CODE |
pasky | 0:9858347c382d | 593 | http.sendstr("GET /history/"); |
pasky | 0:9858347c382d | 594 | http.sendstr(m_subscribe_key); |
pasky | 0:9858347c382d | 595 | http.sendstr("/"); |
pasky | 0:9858347c382d | 596 | http.sendstr(channel); |
pasky | 0:9858347c382d | 597 | http.sendstr("/0/"); |
pasky | 0:9858347c382d | 598 | char limitbuf[8]; snprintf(limitbuf, sizeof(limitbuf), "%d", limit); |
pasky | 0:9858347c382d | 599 | http.sendstr(limitbuf); |
embeddedartists | 7:55eb53c78b47 | 600 | #else |
embeddedartists | 7:55eb53c78b47 | 601 | char buff[200]; |
embeddedartists | 7:55eb53c78b47 | 602 | snprintf(buff, 200, "GET /history/%s/%s/0/%d", m_subscribe_key, channel, limit); |
embeddedartists | 7:55eb53c78b47 | 603 | http.sendstr(buff); |
embeddedartists | 7:55eb53c78b47 | 604 | #endif |
pasky | 0:9858347c382d | 605 | |
pasky | 0:9858347c382d | 606 | char *replybuf = NULL; |
pasky | 0:9858347c382d | 607 | int replylen; |
pasky | 0:9858347c382d | 608 | res = http.http_request_bh(origin_hostname(), &replybuf, &replylen); |
pasky | 0:9858347c382d | 609 | if (res != PNR_OK) |
pasky | 0:9858347c382d | 610 | goto error; |
pasky | 0:9858347c382d | 611 | |
pasky | 0:9858347c382d | 612 | /* Extract from the array and split it. */ |
pasky | 0:9858347c382d | 613 | |
pasky | 0:9858347c382d | 614 | if (replybuf[0] != '[' || replybuf[replylen-1] != ']') { |
pasky | 0:9858347c382d | 615 | res = PNR_FORMAT_ERROR; |
pasky | 0:9858347c382d | 616 | goto error; |
pasky | 0:9858347c382d | 617 | } |
pasky | 0:9858347c382d | 618 | |
pasky | 0:9858347c382d | 619 | replylen -= 2; |
pasky | 0:9858347c382d | 620 | if (replylen == 0) { /* The reply was [] */ |
pasky | 0:9858347c382d | 621 | free(replybuf); |
pasky | 0:9858347c382d | 622 | *reply = NULL; |
pasky | 0:9858347c382d | 623 | *replysize = 0; |
pasky | 0:9858347c382d | 624 | return PNR_OK; |
pasky | 0:9858347c382d | 625 | } |
pasky | 0:9858347c382d | 626 | |
pasky | 0:9858347c382d | 627 | memmove(replybuf, replybuf + 1, replylen); |
pasky | 0:9858347c382d | 628 | replybuf[replylen] = 0; |
pasky | 0:9858347c382d | 629 | |
pasky | 0:9858347c382d | 630 | res = split_array(replybuf, replylen); |
pasky | 0:9858347c382d | 631 | if (res != PNR_OK) |
pasky | 0:9858347c382d | 632 | goto error; |
pasky | 0:9858347c382d | 633 | |
pasky | 0:9858347c382d | 634 | *reply = replybuf; |
pasky | 0:9858347c382d | 635 | *replysize = replylen; |
pasky | 0:9858347c382d | 636 | return PNR_OK; |
pasky | 0:9858347c382d | 637 | |
pasky | 0:9858347c382d | 638 | error: |
pasky | 0:9858347c382d | 639 | free(replybuf); |
embeddedartists | 7:55eb53c78b47 | 640 | //return res; |
embeddedartists | 7:55eb53c78b47 | 641 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 642 | } |
pasky | 0:9858347c382d | 643 | |
pasky | 0:9858347c382d | 644 | |
pasky | 0:9858347c382d | 645 | PubNubRes |
pasky | 0:9858347c382d | 646 | PubNub::time(char *ts) |
pasky | 0:9858347c382d | 647 | { |
pasky | 0:9858347c382d | 648 | PubNubHTTP http; |
pasky | 0:9858347c382d | 649 | PubNubRes res = http.http_connect(origin_hostname()); |
pasky | 0:9858347c382d | 650 | if (res != PNR_OK) |
embeddedartists | 7:55eb53c78b47 | 651 | //return res; |
embeddedartists | 7:55eb53c78b47 | 652 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 653 | |
pasky | 0:9858347c382d | 654 | http.sendstr("GET /time/0"); |
pasky | 0:9858347c382d | 655 | |
pasky | 0:9858347c382d | 656 | char *reply; |
pasky | 0:9858347c382d | 657 | int replylen; |
pasky | 0:9858347c382d | 658 | res = http.http_request_bh(origin_hostname(), &reply, &replylen); |
pasky | 0:9858347c382d | 659 | if (res != PNR_OK) |
embeddedartists | 7:55eb53c78b47 | 660 | //return res; |
embeddedartists | 7:55eb53c78b47 | 661 | PNUB_RETURN_STAT(res); |
pasky | 0:9858347c382d | 662 | |
pasky | 0:9858347c382d | 663 | if (replylen < 3 || replylen > 32 || reply[0] != '[' || reply[replylen-1] != ']') { |
pasky | 0:9858347c382d | 664 | free(reply); |
embeddedartists | 7:55eb53c78b47 | 665 | //return PNR_FORMAT_ERROR; |
embeddedartists | 7:55eb53c78b47 | 666 | PNUB_RETURN_STAT(PNR_FORMAT_ERROR); |
pasky | 0:9858347c382d | 667 | } |
pasky | 0:9858347c382d | 668 | |
pasky | 0:9858347c382d | 669 | replylen -= 2; |
pasky | 0:9858347c382d | 670 | memcpy(ts, reply + 1, replylen); |
pasky | 0:9858347c382d | 671 | ts[replylen] = 0; |
pasky | 0:9858347c382d | 672 | |
pasky | 0:9858347c382d | 673 | free(reply); |
pasky | 0:9858347c382d | 674 | return PNR_OK; |
embeddedartists | 7:55eb53c78b47 | 675 | } |