summaryrefslogtreecommitdiff
path: root/examples/c-json-stdout/c-json-stdout.c
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2020-08-04 22:38:08 +0200
committerToni Uhlig <matzeton@googlemail.com>2020-08-04 22:38:08 +0200
commitd828ef1bf0a99b50034a4971a505a30acb567f65 (patch)
treed56630e52ad289dfdbb0bbb3a3e8ac08d64d78d2 /examples/c-json-stdout/c-json-stdout.c
parent8a6021268e83b8712acc8d73ab2f4073ee402245 (diff)
json buffering and parsing
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'examples/c-json-stdout/c-json-stdout.c')
-rw-r--r--examples/c-json-stdout/c-json-stdout.c104
1 files changed, 95 insertions, 9 deletions
diff --git a/examples/c-json-stdout/c-json-stdout.c b/examples/c-json-stdout/c-json-stdout.c
index ff84a6411..d3a312030 100644
--- a/examples/c-json-stdout/c-json-stdout.c
+++ b/examples/c-json-stdout/c-json-stdout.c
@@ -1,12 +1,16 @@
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "config.h"
+#ifdef USE_JSON
#include "jsmn/jsmn.h"
+#endif
static char serv_listen_addr[INET_ADDRSTRLEN] = DISTRIBUTOR_HOST;
static uint16_t serv_listen_port = DISTRIBUTOR_PORT;
@@ -17,35 +21,117 @@ int main(void)
struct sockaddr_in remote_addr = {};
socklen_t remote_addrlen = sizeof(remote_addr);
uint8_t buf[NETWORK_BUFFER_MAX_SIZE];
- //size_t buf_used = 0;
- //unsigned long long int buf_wanted = 0;
+ size_t buf_used = 0;
+ size_t json_start = 0;
+ unsigned long long int buf_wanted = 0;
+#ifdef USE_JSON
+ jsmn_parser parser;
+ jsmntok_t tokens[128];
+#endif
- if (sockfd < 0) {
+ if (sockfd < 0)
+ {
perror("socket");
return 1;
}
remote_addr.sin_family = AF_INET;
- if (inet_pton(AF_INET, &serv_listen_addr[0], &remote_addr.sin_addr) != 1) {
+ if (inet_pton(AF_INET, &serv_listen_addr[0], &remote_addr.sin_addr) != 1)
+ {
perror("inet_pton");
return 1;
}
remote_addr.sin_port = htons(serv_listen_port);
- if (connect(sockfd, (struct sockaddr *) &remote_addr, remote_addrlen) != 0) {
+ if (connect(sockfd, (struct sockaddr *)&remote_addr, remote_addrlen) != 0)
+ {
perror("connect");
return 1;
}
- while (1) {
+ while (1)
+ {
errno = 0;
- ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
+ ssize_t bytes_read = read(sockfd, buf + buf_used, sizeof(buf) - buf_used);
- if (bytes_read <= 0 || errno != 0) {
+ if (bytes_read <= 0 || errno != 0)
+ {
break;
}
- printf("RECV[%zd]: '%.*s'\n\n", bytes_read, (int) bytes_read, buf);
+ buf_used += bytes_read;
+ if (buf_wanted == 0)
+ {
+ char * json_str_start = NULL;
+ errno = 0;
+ /* the first bytes are the textual representation of the following JSON string */
+ buf_wanted = strtoull((char *)buf, &json_str_start, 10);
+ json_start = (uint8_t *)json_str_start - buf;
+ buf_wanted += json_start;
+
+ if (errno == ERANGE)
+ {
+ buf_used = 0;
+ buf_wanted = 0;
+ fprintf(stderr, "Size of JSON exceeds limit\n");
+ continue;
+ }
+ if ((uint8_t *)json_str_start == buf)
+ {
+ fprintf(stderr, "Missing size before JSON string: %.*s\n", (int)buf_used, buf);
+ buf_used = 0;
+ buf_wanted = 0;
+ continue;
+ }
+ if (buf_wanted > sizeof(buf))
+ {
+ fprintf(stderr, "BUG: JSON string too big: %llu > %zu\n", buf_wanted, sizeof(buf));
+ buf_used = 0;
+ buf_wanted = 0;
+ continue;
+ }
+ }
+
+ /* buffered enough data (full JSON String) ? */
+ if (buf_wanted > buf_used)
+ {
+ continue;
+ }
+ /* after buffering complete, last character should always be a '}' (end of object) */
+ if (buf[buf_wanted - 1] != '}')
+ {
+ fprintf(stderr, "Invalid JSON string: %.*s\n", (int)buf_wanted, buf);
+ buf_used = 0;
+ buf_wanted = 0;
+ continue;
+ }
+
+#ifdef USE_JSON
+ int r;
+ jsmn_init(&parser);
+ r = jsmn_parse(&parser, (char *)(buf + json_start), buf_wanted - json_start,
+ tokens, sizeof(tokens) / sizeof(tokens[0]));
+ if (r < 0 || tokens[0].type != JSMN_OBJECT) {
+ fprintf(stderr, "JSON parsing failed with return value %d at position %u\n", r, parser.pos);
+ fprintf(stderr, "JSON string: '%.*s'\n", (int)(buf_wanted - json_start), (char *)(buf + json_start));
+ }
+
+ for (int i = 1; i < r; i++) {
+ if (i % 2 == 1) {
+ printf("[%.*s : ", tokens[i].end - tokens[i].start,
+ (char *)(buf + json_start) + tokens[i].start);
+ } else {
+ printf("%.*s] ", tokens[i].end - tokens[i].start,
+ (char *)(buf + json_start) + tokens[i].start);
+ }
+ }
+ printf("EoF\n");
+#else
+ printf("RECV[%llu,%zd]: '%.*s'\n\n", buf_wanted, bytes_read, (int)buf_wanted, buf);
+#endif
+ memmove(buf, buf + buf_wanted, buf_used - buf_wanted);
+ buf_used -= buf_wanted;
+ buf_wanted = 0;
}
return 0;