X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fdevtools.c;h=d14d1d81370cdadf7d18232585b02bdcd2861003;hb=d0bf55f32b407fa153dd5d6e41ccefcbb4072611;hp=2a98e595054850a78fecd489058acba6914db846;hpb=8582c3b5e0ee3f6b547dbaed7a1214819d3dfc91;p=meshlink-tiny diff --git a/src/devtools.c b/src/devtools.c index 2a98e59..d14d1d8 100644 --- a/src/devtools.c +++ b/src/devtools.c @@ -55,210 +55,6 @@ void (*devtool_set_inviter_commits_first)(bool inviter_commited_first) = inviter void (*devtool_adns_resolve_probe)(void) = nop_probe; void (*devtool_sptps_renewal_probe)(meshlink_node_t *node) = sptps_renewal_nop_probe; -/* Return an array of edges in the current network graph. - * Data captures the current state and will not be updated. - * Caller must deallocate data when done. - */ -devtool_edge_t *devtool_get_all_edges(meshlink_handle_t *mesh, devtool_edge_t *edges, size_t *nmemb) { - if(!mesh || !nmemb || (*nmemb && !edges)) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - devtool_edge_t *result = NULL; - unsigned int result_size = 0; - - result_size = mesh->edges->count / 2; - - // if result is smaller than edges, we have to dealloc all the excess devtool_edge_t - if((size_t)result_size > *nmemb) { - result = xrealloc(edges, result_size * sizeof(*result)); - } else { - result = edges; - } - - if(result) { - devtool_edge_t *p = result; - unsigned int n = 0; - - for splay_each(edge_t, e, mesh->edges) { - // skip edges that do not represent a two-directional connection - if(!e->reverse || e->reverse->to != e->from) { - continue; - } - - // don't count edges twice - if(e->to < e->from) { - continue; - } - - assert(n < result_size); - - p->from = (meshlink_node_t *)e->from; - p->to = (meshlink_node_t *)e->to; - p->address = e->address.storage; - p->weight = e->weight; - - n++; - p++; - } - - // shrink result to the actual amount of memory used - result = xrealloc(result, n * sizeof(*result)); - *nmemb = n; - } else { - *nmemb = 0; - meshlink_errno = MESHLINK_ENOMEM; - } - - pthread_mutex_unlock(&mesh->mutex); - - return result; -} - -static bool fstrwrite(const char *str, FILE *stream) { - assert(stream); - - size_t len = strlen(str); - - if(fwrite((void *)str, 1, len, stream) != len) { - return false; - } - - return true; -} - -bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream) { - assert(stream); - - bool result = true; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - // export edges and nodes - size_t node_count = 0; - size_t edge_count = 0; - - meshlink_node_t **nodes = meshlink_get_all_nodes(mesh, NULL, &node_count); - devtool_edge_t *edges = devtool_get_all_edges(mesh, NULL, &edge_count); - - if((!nodes && node_count != 0) || (!edges && edge_count != 0)) { - goto fail; - } - - // export begin - if(!fstrwrite("{\n", stream)) { - goto fail; - } - - // export nodes - if(!fstrwrite("\t\"nodes\": {\n", stream)) { - goto fail; - } - - char buf[16]; - - for(size_t i = 0; i < node_count; ++i) { - if(!fstrwrite("\t\t\"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\": {\n", stream)) { - goto fail; - } - - if(!fstrwrite("\t\t\t\"name\": \"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\",\n", stream)) { - goto fail; - } - - snprintf(buf, sizeof(buf), "%d", ((node_t *)nodes[i])->devclass); - - if(!fstrwrite("\t\t\t\"devclass\": ", stream) || !fstrwrite(buf, stream) || !fstrwrite("\n", stream)) { - goto fail; - } - - if(!fstrwrite((i + 1) != node_count ? "\t\t},\n" : "\t\t}\n", stream)) { - goto fail; - } - } - - if(!fstrwrite("\t},\n", stream)) { - goto fail; - } - - // export edges - - if(!fstrwrite("\t\"edges\": {\n", stream)) { - goto fail; - } - - for(size_t i = 0; i < edge_count; ++i) { - if(!fstrwrite("\t\t\"", stream) || !fstrwrite(edges[i].from->name, stream) || !fstrwrite("_to_", stream) || !fstrwrite(edges[i].to->name, stream) || !fstrwrite("\": {\n", stream)) { - goto fail; - } - - if(!fstrwrite("\t\t\t\"from\": \"", stream) || !fstrwrite(edges[i].from->name, stream) || !fstrwrite("\",\n", stream)) { - goto fail; - } - - if(!fstrwrite("\t\t\t\"to\": \"", stream) || !fstrwrite(edges[i].to->name, stream) || !fstrwrite("\",\n", stream)) { - goto fail; - } - - char *host = NULL, *port = NULL, *address = NULL; - sockaddr2str((const sockaddr_t *)&edges[i].address, &host, &port); - - if(host && port) { - xasprintf(&address, "{ \"host\": \"%s\", \"port\": %s }", host, port); - } - - free(host); - free(port); - - if(!fstrwrite("\t\t\t\"address\": ", stream) || !fstrwrite(address ? address : "null", stream) || !fstrwrite(",\n", stream)) { - free(address); - goto fail; - } - - free(address); - - snprintf(buf, sizeof(buf), "%d", edges[i].weight); - - if(!fstrwrite("\t\t\t\"weight\": ", stream) || !fstrwrite(buf, stream) || !fstrwrite("\n", stream)) { - goto fail; - } - - if(!fstrwrite((i + 1) != edge_count ? "\t\t},\n" : "\t\t}\n", stream)) { - goto fail; - } - } - - if(!fstrwrite("\t}\n", stream)) { - goto fail; - } - - // DONE! - - if(!fstrwrite("}", stream)) { - goto fail; - } - - goto done; - -fail: - result = false; - -done: - free(nodes); - free(edges); - - pthread_mutex_unlock(&mesh->mutex); - - return result; -} - void devtool_get_node_status(meshlink_handle_t *mesh, meshlink_node_t *node, devtool_node_status_t *status) { if(!mesh || !node || !status) { meshlink_errno = MESHLINK_EINVAL;