]> git.meshlink.io Git - meshlink/blob - src/devtools.c
Enforce spaces around operators.
[meshlink] / src / devtools.c
1
2 #include "system.h"
3
4 #include "logger.h"
5 #include "meshlink_internal.h"
6 #include "node.h"
7 #include "splay_tree.h"
8 #include "netutl.h"
9 #include "xalloc.h"
10
11 #include "devtools.h"
12
13 static int node_compare(const void *a, const void *b) {
14         if(a < b)
15                 return -1;
16
17         if(a > b)
18                 return 1;
19
20         return 0;
21 }
22
23 static bool fstrwrite(const char *str, FILE *stream) {
24         size_t len = strlen(str);
25
26         if(fwrite((void *)str, 1, len, stream) != len)
27                 return false;
28
29         return true;
30 }
31
32 static const char *__itoa(int value) {
33         static char buffer[sizeof(int) * 8 + 1];        // not thread safe
34
35         if(snprintf(buffer, sizeof(buffer), "%d", value) == -1)
36                 return "";
37
38         return buffer;
39 }
40
41 bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE *stream) {
42         bool result = true;
43
44         pthread_mutex_lock(&(mesh->mesh_mutex));
45
46         // export edges and nodes
47         size_t node_count = 0;
48         size_t edge_count = 0;
49
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);
52
53         if((!nodes && node_count != 0) || (!edges && edge_count != 0))
54                 goto fail;
55
56         // export begin
57         if(!fstrwrite("{\n", stream))
58                 goto fail;
59
60         // export nodes
61         if(!fstrwrite("\t\"nodes\": {\n", stream))
62                 goto fail;
63
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))
66                         goto fail;
67
68                 if(!fstrwrite("\t\t\t\"name\": \"", stream) || !fstrwrite(((node_t *)nodes[i])->name, stream) || !fstrwrite("\",\n", stream))
69                         goto fail;
70
71                 if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->options), stream) || !fstrwrite(",\n", stream))
72                         goto fail;
73
74                 if(!fstrwrite("\t\t\t\"devclass\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->devclass), stream) || !fstrwrite("\n", stream))
75                         goto fail;
76
77                 if(!fstrwrite((i + 1) != node_count ? "\t\t},\n" : "\t\t}\n", stream))
78                         goto fail;
79         }
80
81         if(!fstrwrite("\t},\n", stream))
82                 goto fail;
83
84         // export edges
85
86         if(!fstrwrite("\t\"edges\": {\n", stream))
87                 goto fail;
88
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))
91                         goto fail;
92
93                 if(!fstrwrite("\t\t\t\"from\": \"", stream) || !fstrwrite(edges[i]->from->name, stream) || !fstrwrite("\",\n", stream))
94                         goto fail;
95
96                 if(!fstrwrite("\t\t\t\"to\": \"", stream) || !fstrwrite(edges[i]->to->name, stream) || !fstrwrite("\",\n", stream))
97                         goto fail;
98
99                 char *host = NULL, *port = NULL, *address = NULL;
100                 sockaddr2str((const sockaddr_t *) & (edges[i]->address), &host, &port);
101
102                 if(host && port)
103                         xasprintf(&address, "{ \"host\": \"%s\", \"port\": %s }", host, port);
104
105                 free(host);
106                 free(port);
107
108                 if(!fstrwrite("\t\t\t\"address\": ", stream) || !fstrwrite(address ? address : "null", stream) || !fstrwrite(",\n", stream)) {
109                         free(address);
110                         goto fail;
111                 }
112
113                 free(address);
114
115                 if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(edges[i]->options), stream) || !fstrwrite(",\n", stream))
116                         goto fail;
117
118                 if(!fstrwrite("\t\t\t\"weight\": ", stream) || !fstrwrite(__itoa(edges[i]->weight), stream) || !fstrwrite("\n", stream))
119                         goto fail;
120
121                 if(!fstrwrite((i + 1) != edge_count ? "\t\t},\n" : "\t\t}\n", stream))
122                         goto fail;
123         }
124
125         if(!fstrwrite("\t}\n", stream))
126                 goto fail;
127
128         // DONE!
129
130         if(!fstrwrite("}", stream))
131                 goto fail;
132
133         goto done;
134
135 fail:
136         result = false;
137
138 done:
139
140         if(nodes)
141                 free(nodes);
142
143         for(size_t i = 0; edges && i < edge_count; ++i)
144                 free(edges[i]);
145
146         if(nodes)
147                 free(edges);
148
149         pthread_mutex_unlock(&(mesh->mesh_mutex));
150
151         return result;
152 }