commit 2c8b700a9aa63cdb35c0ec3e2c8d6d5de8500532
parent fcc6c15637cb7807516ebd8fa2830ef6fadbebf9
Author: William Casarin <jb55@jb55.com>
Date: Sat, 11 Aug 2018 15:09:35 -0700
node parsing working
Diffstat:
M | Makefile | | | 2 | +- |
M | json.c | | | 163 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
M | json.h | | | 11 | +++++++---- |
M | ln.c | | | 2 | +- |
M | ln.h | | | 3 | ++- |
M | main.c | | | 38 | ++++++++++++++++++++++++++++++++------ |
6 files changed, 191 insertions(+), 28 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,7 +1,7 @@
BIN = lnvis
PREFIX ?= /usr/local
-CFLAGS = -Ideps -ggdb -O2 -Wall -Wextra -Werror -std=c99 -DJSMN_PARENT_LINKS
+CFLAGS = -Ideps -ggdb -O2 -Wall -Wextra -std=c99 -DJSMN_PARENT_LINKS
LDFLAGS = -lglfw -lGL
diff --git a/json.c b/json.c
@@ -4,17 +4,29 @@
#include <stdio.h>
#include <assert.h>
#include <stdio.h>
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#define ERROR_READING_CHANNELS -2
#define ERROR_ALLOCATING_CHANNELS -3
-struct parser {
+#define min(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+struct channel_parser {
const char *field;
enum channel_parsing_state state;
};
+
+struct node_parser {
+ const char *field;
+ enum node_parsing_state state;
+};
+
/* "source": "02fc7ef232bd958209a2180fb18844388babc48a81d31434e343ecc4d7dd1a9186", */
/* "destination": "03b7ca940bc33b882dc1f1bee353a6cf205b1a7472d8ae24d45370a8f510c27d23", */
/* "short_channel_id": "505273:1478:0", */
@@ -26,7 +38,7 @@ struct parser {
/* "base_fee_millisatoshi": 1, */
/* "fee_per_millionth": 1, */
/* "delay": 14 */
-static const struct parser channel_parsers[] = {
+static const struct channel_parser channel_parsers[] = {
{ "short_channel_id", PARSING_CHAN_SHORTID },
{ "public", PARSING_CHAN_PUBLIC },
{ "satoshis", PARSING_CHAN_SATOSHIS },
@@ -38,6 +50,22 @@ static const struct parser channel_parsers[] = {
{ "delay", PARSING_CHAN_DELAY },
};
+/* "nodeid": "03a8334aba5660e241468e2f0deb2526bfd50d0e3fe808d882913e39094dc1a028", */
+/* "alias": "cosmicApotheosis", */
+/* "color": "33cccc", */
+/* "last_timestamp": 1533693585, */
+/* "global_features": "", */
+/* "addresses": [ */
+/* { "type": "ipv4", */
+/* "address": "138.229.205.237", */
+/* "port": 9735 */
+/* }] */
+static const struct node_parser node_parsers[] = {
+ { "alias", PARSING_NODE_ALIAS },
+ { "color", PARSING_NODE_COLOR },
+ { "addresses", PARSING_NODE_ADDRESSES },
+};
+
#define MKTMPBUF \
char buf[toklen + 1]; \
buf[toklen] = '\0'; \
@@ -141,36 +169,141 @@ int parse_json(FILE *fd, jsmntok_t **ptoks, int *ntoks, char **pbuffer) {
}
+static inline u8 hexdigit(char hex) {
+ return (hex <= '9') ? hex - '0' : toupper(hex) - 'A' + 10 ;
+}
+
+
+static void parse_color(int toklen, const char *tokstr, union color *color) {
+ color->a = 1.0f;
+
+ if (toklen != 6)
+ goto colorerr;
+
+ for (int i = 0; i < 3; i++) {
+ u8 c1 = tokstr[i];
+ u8 c2 = tokstr[i+1];
+
+ if (!isxdigit(c1) || !isxdigit(c2))
+ goto colorerr;
+
+ u8 val = hexdigit(c1) << 4 | hexdigit(c2);
+ color->rgba[i] = val / 255.0f;
+ }
+
+ return;
+colorerr:
+ color->r = 0.0f;
+ color->g = 0.0f;
+ color->b = 0.0f;
+ return;
+}
+
int parse_clightning_nodes(FILE *fd, int *node_count, struct node **pnodes)
{
- (void)fd;
- (void)node_count;
- (void)pnodes;
+ struct node *node = NULL, *nodes;
+ char *buffer, *tokstr;
+ void *res;
+ jsmntok_t *toks;
+ jsmntok_t *tok;
+ int i, ntoks = 0, toklen = 0, objs = 0;
+ int nodecap = 4096;
+ enum node_parsing_state state = PARSING_NODE_TOKEN;
+
+ *node_count = 0;
+
+ nodes = calloc(nodecap, sizeof(struct node));
+
+ int rez = parse_json(fd, &toks, &ntoks, &buffer);
+ if (rez < 0)
+ return rez;
+
+ for (i = 0; i < ntoks; i++) {
+ tok = &toks[i];
+
+ if (tok->type == JSMN_ARRAY)
+ continue;
+
+ if (tok->type == JSMN_OBJECT) {
+ if (state == PARSING_NODE_ADDRESSES)
+ continue;
+
+ if (++objs > 2)
+ (*node_count)++;
+
+ continue;
+ }
+
+ toklen = tok->end - tok->start;
+ tokstr = &buffer[tok->start];
+
+ node = &nodes[*node_count];
+
+ // allocate more channels if needed
+ if (*node_count > nodecap) {
+ nodecap *= 2;
+ res = realloc(nodes, nodecap * sizeof(struct channel));
+ if (res == NULL) {
+ free(nodes);
+ return ERROR_ALLOCATING_CHANNELS;
+ }
+ nodes = res;
+ }
+
+ switch (state) {
+ case PARSING_NODE_ALIAS:
+ strncpy(node->alias, tokstr, min(toklen, MAX_ALIAS_SIZE));
+ state = PARSING_NODE_TOKEN;
+ break;
+
+ case PARSING_NODE_COLOR:
+ parse_color(toklen, tokstr, &node->color);
+ state = PARSING_NODE_TOKEN;
+ break;
+
+ case PARSING_NODE_ADDRESSES:
+ // TODO: parse addresses
+ state = PARSING_NODE_TOKEN;
+ break;
+
+ case PARSING_NODE_TOKEN:
+ for (size_t i = 0; i < ARRAY_SIZE(node_parsers); i++) {
+ if (tokeq(toklen, tokstr,
+ node_parsers[i].field)) {
+ state = node_parsers[i].state;
+ continue;
+ }
+ }
+ break;
+ }
+
+ }
+
+ *pnodes = nodes;
+ *node_count = *node_count + 1;
+
return 0;
}
-int parse_clightning_channels(FILE *fd, int *nchannels, struct channel **pchannels)
+int parse_clightning_channels(FILE *fd, int *nchans, struct channel **pchannels)
{
char *buffer;
void *res;
struct channel *chan = NULL, *channels;
- int nchans = 0;
int chancap = 4096;
jsmntok_t *toks;
jsmntok_t *tok;
char *tokstr;
- int ntoks;
- int toklen;
+ int ntoks = 0, toklen = 0, objs = 0;
enum channel_parsing_state state = PARSING_CHAN_TOKEN;
+
int rez = parse_json(fd, &toks, &ntoks, &buffer);
if (rez < 0)
return rez;
channels = calloc(chancap, sizeof(struct channel));
- int objs = 0;
-
// parse tokens
for (int i = 0; i < ntoks; ++i) {
tok = &toks[i];
@@ -180,7 +313,7 @@ int parse_clightning_channels(FILE *fd, int *nchannels, struct channel **pchanne
if (tok->type == JSMN_OBJECT) {
if (++objs > 2)
- nchans++;
+ (*nchans)++;
continue;
}
@@ -189,7 +322,7 @@ int parse_clightning_channels(FILE *fd, int *nchannels, struct channel **pchanne
tokstr = &buffer[tok->start];
// allocate more channels if needed
- if (nchans > chancap) {
+ if (*nchans > chancap) {
chancap *= 2;
res = realloc(channels, chancap * sizeof(struct channel));
if (res == NULL) {
@@ -199,7 +332,7 @@ int parse_clightning_channels(FILE *fd, int *nchannels, struct channel **pchanne
channels = res;
}
- chan = &channels[nchans];
+ chan = &channels[*nchans];
// TODO: lookup node id, assign nodes
switch (state) {
@@ -263,7 +396,7 @@ int parse_clightning_channels(FILE *fd, int *nchannels, struct channel **pchanne
}
*pchannels = channels;
- *nchannels = nchans + 1;
+ *nchans = *nchans + 1;
free(buffer);
free(toks);
diff --git a/json.h b/json.h
@@ -6,8 +6,11 @@
#include <stdio.h>
#include "ln.h"
-enum nodes_parsing_state {
- PARSING_NODE_TOKEN
+enum node_parsing_state {
+ PARSING_NODE_TOKEN,
+ PARSING_NODE_ALIAS,
+ PARSING_NODE_COLOR,
+ PARSING_NODE_ADDRESSES,
};
enum channel_parsing_state {
@@ -23,7 +26,7 @@ enum channel_parsing_state {
PARSING_CHAN_DELAY,
};
-int parse_clightning_channels(FILE *fd, int *nchannels,
- struct channel **channels);
+int parse_clightning_nodes(FILE *fd, int *node_count, struct node **nodes);
+int parse_clightning_channels(FILE *fd, int *nchannels, struct channel **channels);
#endif /* LNVIS_JSON_H */
diff --git a/ln.c b/ln.c
@@ -37,7 +37,7 @@ void random_network(int ww, int wh, int max_per_node, int num_nodes, struct ln *
for (i = 0; i < num_nodes; ++i) {
n = &ln->nodes[i];
- n->alias = "test";
+ strcpy(n->alias, "test");
n->color.r = rand_0to1();
n->color.g = rand_0to1();
n->color.b = rand_0to1();
diff --git a/ln.h b/ln.h
@@ -6,6 +6,7 @@
#include "defs.h"
#define CELL_MAX_ELEMS 32
+#define MAX_ALIAS_SIZE 32
union color {
float rgba[4];
@@ -16,7 +17,7 @@ union color {
};
struct node {
- const char *alias;
+ char alias[MAX_ALIAS_SIZE];
const char *id; // pubkey
union color color;
diff --git a/main.c b/main.c
@@ -101,6 +101,14 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
}
}
+static void print_node(struct node *node)
+{
+ printf("node %s #%02X%02X%02X\n", node->alias,
+ (int)node->color.r * 255,
+ (int)node->color.g * 255,
+ (int)node->color.b * 255);
+}
+
static void print_channel(struct channel *chan)
{
printf("chan shortid=%u:%u:%hu public=%d sats=%"PRIu64" active=%d "
@@ -121,22 +129,40 @@ static void print_channel(struct channel *chan)
void test_read_json()
{
- FILE *f = fopen("clightning-channels.json", "r");
+ FILE *channels_fd = fopen("clightning-channels.json", "r");
+ FILE *nodes_fd = fopen("clightning-nodes.json", "r");
+
int nchans = 0;
+ int node_count = 0;
+ int i;
struct channel *channels;
- int res = parse_clightning_channels(f, &nchans, &channels);
+ struct node *nodes;
+
+ int res = parse_clightning_nodes(nodes_fd, &node_count, &nodes);
+ fclose(nodes_fd);
+
+ if (res != 0) {
+ printf("parse_clightning_nodes res %d\n", res);
+ exit(1);
+ }
+
+ res = parse_clightning_channels(channels_fd, &nchans, &channels);
+ fclose(channels_fd);
if (res != 0) {
- printf("test_read_json res %d\n", res);
+ printf("parse_clightning_channels res %d\n", res);
exit(1);
}
- for (int i = 0; i < nchans; i++)
+ for (i = 0; i < nchans; i++)
print_channel(&channels[i]);
- printf("%d channels\n", nchans);
+ for (i = 0; i < node_count; i++)
+ print_node(&nodes[i]);
+
+ printf("%d nodes, %d channels\n", node_count, nchans);
+
- fclose(f);
exit(0);
}