5 #include "meshlink_internal.h"
7 #include "splay_tree.h"
13 static int node_compare(const void *a, const void *b) {
23 static bool fstrwrite(const char *str, FILE *stream) {
24 size_t len = strlen(str);
26 if(fwrite((void *)str, 1, len, stream) != len)
32 static const char *__itoa(int value) {
33 static char buffer[sizeof(int) * 8 + 1]; // not thread safe
35 if(snprintf(buffer, sizeof(buffer), "%d", value) == -1)
41 bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream) {
44 pthread_mutex_lock(&(mesh->mesh_mutex));
46 // export edges and nodes
47 size_t node_count = 0;
48 size_t edge_count = 0;
50 meshlink_node_t **nodes = meshlink_get_all_nodes(mesh, NULL, &node_count);
51 meshlink_edge_t **edges = meshlink_get_all_edges_state(mesh, NULL, &edge_count);
53 if((!nodes && node_count != 0) || (!edges && edge_count != 0))
57 if(!fstrwrite("{\n", stream))
61 if(!fstrwrite("\t\"nodes\": {\n", stream))
64 for(size_t i = 0; i < node_count; ++i) {
65 if(!fstrwrite("\t\t\"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\": {\n", stream))
68 if(!fstrwrite("\t\t\t\"name\": \"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\",\n", stream))
71 if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->options), stream) || !fstrwrite(",\n", stream))
74 if(!fstrwrite("\t\t\t\"devclass\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->devclass), stream) || !fstrwrite("\n", stream))
77 if(!fstrwrite((i + 1) != node_count ? "\t\t},\n" : "\t\t}\n", stream))
81 if(!fstrwrite("\t},\n", stream))
86 if(!fstrwrite("\t\"edges\": {\n", stream))
89 for(size_t i = 0; i < edge_count; ++i) {
90 if(!fstrwrite("\t\t\"", stream) || !fstrwrite(edges[i]->from->name, stream) || !fstrwrite("_to_", stream) || !fstrwrite(edges[i]->to->name, stream) || !fstrwrite("\": {\n", stream))
93 if(!fstrwrite("\t\t\t\"from\": \"", stream) || !fstrwrite(edges[i]->from->name, stream) || !fstrwrite("\",\n", stream))
96 if(!fstrwrite("\t\t\t\"to\": \"", stream) || !fstrwrite(edges[i]->to->name, stream) || !fstrwrite("\",\n", stream))
99 char *host = NULL, *port = NULL, *address = NULL;
100 sockaddr2str((const sockaddr_t *) & (edges[i]->address), &host, &port);
103 xasprintf(&address, "{ \"host\": \"%s\", \"port\": %s }", host, port);
108 if(!fstrwrite("\t\t\t\"address\": ", stream) || !fstrwrite(address ? address : "null", stream) || !fstrwrite(",\n", stream)) {
115 if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(edges[i]->options), stream) || !fstrwrite(",\n", stream))
118 if(!fstrwrite("\t\t\t\"weight\": ", stream) || !fstrwrite(__itoa(edges[i]->weight), stream) || !fstrwrite("\n", stream))
121 if(!fstrwrite((i + 1) != edge_count ? "\t\t},\n" : "\t\t}\n", stream))
125 if(!fstrwrite("\t}\n", stream))
130 if(!fstrwrite("}", stream))
143 for(size_t i = 0; edges && i < edge_count; ++i)
149 pthread_mutex_unlock(&(mesh->mesh_mutex));