]> git.meshlink.io Git - meshlink/blob - examples/manynodes.c
manynodes example: committed /test command to test if it is possible to succefully...
[meshlink] / examples / manynodes.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <strings.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <linux/limits.h>
8
9 #include "../src/meshlink.h"
10
11 static int n = 100;
12 static meshlink_handle_t **mesh;
13
14 static meshlink_node_t **nodes;
15 static size_t nnodes;
16
17 //Test mesh sending data
18 static void testmesh () {
19
20         for(int nindex = 0; nindex < n; nindex++) {
21
22                         nodes = meshlink_get_all_nodes(mesh[nindex], nodes, &nnodes);
23                         if(!nodes) {
24                                 fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno));
25                         } else {
26                                 printf("%zu known nodes:", nnodes);
27                                 for(int i = 0; i < nnodes; i++) {
28                                         printf(" %s", nodes[i]->name);
29                                         if(!meshlink_send(mesh[nindex], nodes[i], "magic", strlen("magic") + 1)) {
30                 fprintf(stderr, "Could not send message to '%s': %s\n", nodes[i]->name, meshlink_strerror(meshlink_errno));
31         }
32         }
33
34                         }
35
36         }
37 }
38 // Make all nodes know about each other by importing each others public keys and addresses.
39 static void linkmesh() {
40         for(int i = 0; i < n; i++) {
41                 char *datai = meshlink_export(mesh[i]);
42
43                 for(int j = i + 1; j < n; j++) {
44                         char *dataj = meshlink_export(mesh[j]);
45                         meshlink_import(mesh[i], dataj);
46                         meshlink_import(mesh[j], datai);
47                         free(dataj);
48                 }
49
50                 free(datai);
51         }
52 }
53
54 static void parse_command(char *buf) {
55         char *arg = strchr(buf, ' ');
56         if(arg)
57                 *arg++ = 0;
58
59         if(!strcasecmp(buf, "invite")) {
60                 char *invitation;
61
62                 if(!arg) {
63                         fprintf(stderr, "/invite requires an argument!\n");
64                         return;
65                 }
66
67                 invitation = meshlink_invite(mesh[0], arg);
68                 if(!invitation) {
69                         fprintf(stderr, "Could not invite '%s': %s\n", arg, meshlink_strerror(meshlink_errno));
70                         return;
71                 }
72
73                 printf("Invitation for %s: %s\n", arg, invitation);
74                 free(invitation);
75         } else if(!strcasecmp(buf, "join")) {
76                 if(!arg) {
77                         fprintf(stderr, "/join requires an argument!\n");
78                         return;
79                 }
80                 meshlink_stop(mesh[0]);
81                 if(!meshlink_join(mesh[0], arg))
82                         fprintf(stderr, "Could not join using invitation: %s\n", meshlink_strerror(meshlink_errno));
83                 else {
84                         fprintf(stderr, "Invitation accepted!\n");
85                         meshlink_start(mesh[0]);
86                 }
87         } else if(!strcasecmp(buf, "kick")) {
88                 if(!arg) {
89                         fprintf(stderr, "/kick requires an argument!\n");
90                         return;
91                 }
92
93                 meshlink_node_t *node = meshlink_get_node(mesh[0], arg);
94                 if(!node) {
95                         fprintf(stderr, "Unknown node '%s'\n", arg);
96                         return;
97                 }
98
99                 meshlink_blacklist(mesh[0], node);
100
101                 printf("Node '%s' blacklisted.\n", arg);
102         } else if(!strcasecmp(buf, "who")) {
103                 if(!arg) {
104                         nodes = meshlink_get_all_nodes(mesh[0], nodes, &nnodes);
105                         if(!nodes) {
106                                 fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno));
107                         } else {
108                                 printf("%zu known nodes:", nnodes);
109                                 for(int i = 0; i < nnodes; i++)
110                                         printf(" %s", nodes[i]->name);
111                                 printf("\n");
112                         }
113                 } else {
114                         meshlink_node_t *node = meshlink_get_node(mesh[0], arg);
115                         if(!node) {
116                                 fprintf(stderr, "Unknown node '%s'\n", arg);
117                         } else {
118                                 printf("Node %s found\n", arg);
119                         }
120                 }
121         } else if(!strcasecmp(buf, "link")) {
122                 linkmesh();
123         } else if(!strcasecmp(buf, "test")) {
124                 testmesh();
125         } else if(!strcasecmp(buf, "quit")) {
126                 printf("Bye!\n");
127                 fclose(stdin);
128         } else if(!strcasecmp(buf, "help")) {
129                 printf(
130                         "<name>: <message>     Send a message to the given node.\n"
131                         "                      Subsequent messages don't need the <name>: prefix.\n"
132                         "/invite <name>        Create an invitation for a new node.\n"
133                         "/join <invitation>    Join an existing mesh using an invitation.\n"
134                         "/kick <name>          Blacklist the given node.\n"
135                         "/who [<name>]         List all nodes or show information about the given node.\n"
136                         "/link                 Link all nodes together.\n"
137                         "/test                 Test functionality sending some data to all nodes\n"
138                         "/quit                 Exit this program.\n"
139                         );
140         } else {
141                 fprintf(stderr, "Unknown command '/%s'\n", buf);
142         }
143 }
144
145 static void parse_input(char *buf) {
146         static meshlink_node_t *destination;
147         size_t len;
148
149         if(!buf)
150                 return;
151
152         // Remove newline.
153
154         len = strlen(buf);
155
156         if(len && buf[len - 1] == '\n')
157                 buf[--len] = 0;
158
159         if(len && buf[len - 1] == '\r')
160                 buf[--len] = 0;
161
162         // Ignore empty lines.
163
164         if(!len)
165                 return;
166
167         // Commands start with '/'
168
169         if(*buf == '/')
170                 return parse_command(buf + 1);
171
172         // Lines in the form "name: message..." set the destination node.
173
174         char *msg = buf;
175         char *colon = strchr(buf, ':');
176
177         if(colon) {
178                 *colon = 0;
179                 msg = colon + 1;
180                 if(*msg == ' ')
181                         msg++;
182
183                 destination = meshlink_get_node(mesh[0], buf);
184                 if(!destination) {
185                         fprintf(stderr, "Unknown node '%s'\n", buf);
186                         return;
187                 }
188         }
189
190         if(!destination) {
191                 fprintf(stderr, "Who are you talking to? Write 'name: message...'\n");
192                 return;
193         }
194
195         if(!meshlink_send(mesh[0], destination, msg, strlen(msg) + 1)) {
196                 fprintf(stderr, "Could not send message to '%s': %s\n", destination->name, meshlink_strerror(meshlink_errno));
197                 return;
198         }
199
200         printf("Message sent to '%s'.\n", destination->name);
201 }
202
203 int main(int argc, char *argv[]) {
204         const char *basebase = ".manynodes";
205         const char *namesprefix = "machine1";
206         char buf[1024];
207
208         if(argc > 1)
209                 n = atoi(argv[1]);
210
211         if(n < 1) {
212                 fprintf(stderr, "Usage: %s [number of local nodes] [confbase] [prefixnodenames]\n", argv[0]);
213                 return 1;
214         }
215
216         if(argc > 2)
217                 basebase = argv[2];
218
219         if(argc > 3)
220                 namesprefix = argv[3];
221
222         mesh = calloc(n, sizeof *mesh);
223
224         mkdir(basebase, 0750);
225
226         char filename[PATH_MAX];
227         char nodename[100];
228         for(int i = 0; i < n; i++) {
229                 snprintf(nodename, sizeof nodename, "%snode%d", namesprefix,i);
230                 snprintf(filename, sizeof filename, "%s/%s", basebase, nodename);
231                 bool itsnew = access(filename, R_OK);
232                 mesh[i] = meshlink_open(filename, nodename, "manynodes");
233                 if(itsnew)
234                         meshlink_add_address(mesh[i], "localhost");
235                 if(!mesh[i]) {
236                         fprintf(stderr, "errno is: %d\n", meshlink_errno);
237                         fprintf(stderr, "Could not open %s: %s\n", filename, meshlink_strerror(meshlink_errno));
238                         return 1;
239                 }
240         }
241
242         int started = 0;
243
244         for(int i = 0; i < n; i++) {
245                 if(!meshlink_start(mesh[i]))
246                         fprintf(stderr, "Could not start node %d: %s\n", i, meshlink_strerror(meshlink_errno));
247                 else
248                         started++;
249         }
250
251         if(!started) {
252                 fprintf(stderr, "Could not start any node!\n");
253                 return 1;
254         }
255
256         printf("%d nodes started.\nType /help for a list of commands.\n", started);
257
258         while(fgets(buf, sizeof buf, stdin))
259                 parse_input(buf);
260
261         printf("Nodes stopping.\n");
262
263         for(int i = 0; i < n; i++)
264                 meshlink_close(mesh[i]);
265
266         return 0;
267 }