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