… | |
… | |
15 | |
15 | |
16 | # run a node |
16 | # run a node |
17 | aemp run initialise_args... # run a node |
17 | aemp run initialise_args... # run a node |
18 | |
18 | |
19 | # node configuration: protocol endpoints |
19 | # node configuration: protocol endpoints |
20 | aemp setnoderef <noderef> # configure the real noderef |
20 | aemp setnodeid <nodeid> # configure the real node id |
21 | aemp clrnoderef # reset noderef to default |
21 | aemp delnodeid # reset node id to default (= inherit) |
22 | |
22 | |
23 | # node configuration: secret |
23 | # node configuration: secret |
24 | aemp gensecret # generate a random shared secret |
24 | aemp gensecret # generate a random shared secret |
25 | aemp setsecret <secret> # set the shared secret |
25 | aemp setsecret <secret> # set the shared secret |
26 | aemp clrsecret # remove the secret |
26 | aemp delsecret # remove the secret (= inherit) |
27 | |
27 | |
28 | # node configuration: TLS |
28 | # node configuration: TLS |
|
|
29 | aemp gencert # generate a random certificate |
29 | aemp setcert <file> # set a certificate (key.pem + certificate.pem) |
30 | aemp setcert <file> # set a certificate (key.pem + certificate.pem) |
30 | aemp clrcert # remove certificate |
31 | aemp delcert # remove certificate (= inherit) |
31 | aemp gencert # generate a random certificate |
|
|
32 | |
32 | |
33 | # node configuration: seed nodes for bootstrapping |
33 | # node configuration: seed addresses for bootstrapping |
34 | aemp setseeds <noderef>... # set seednodes |
34 | aemp setseeds <host:port>... # set seeds |
|
|
35 | aemp delseeds # clear all seeds (= inherit) |
35 | aemp addseed <noderef> # add a seednode |
36 | aemp addseed <host:port> # add a seed |
36 | aemp delseed <noderef> # remove seednode |
37 | aemp delseed <host:port> # remove seed |
|
|
38 | |
|
|
39 | # node configuration: bind addresses |
|
|
40 | aemp setbinds <host:port>... # set binds |
|
|
41 | aemp delbinds # clear all binds (= inherit) |
|
|
42 | aemp addbind <host:port> # add a bind address |
|
|
43 | aemp delbind <host:port> # remove a bind address |
37 | |
44 | |
38 | # node configuration: services |
45 | # node configuration: services |
39 | aemp setservices initfunc... # set service functions |
46 | aemp setservices initfunc... # set service functions |
|
|
47 | aemp delservices # clear all services (= inherit) |
40 | aemp addservice <initfunc> # add an instance of a service |
48 | aemp addservice <initfunc> # add an instance of a service |
41 | aemp delservice <initfunc> # delete one instance of a service |
49 | aemp delservice <initfunc> # delete one instance of a service |
42 | |
50 | |
43 | # profile-specific configuration |
51 | # profile-specific configuration |
44 | aemp profile <name> <command>... # apply command to profile only |
52 | aemp profile <name> <command>... # apply command to profile only |
45 | aemp delprofile <name> # eradicate the named profile |
53 | aemp delprofile <name> # eradicate the named profile |
|
|
54 | aemp showprofile <name> # display given profile |
|
|
55 | aemp showconfig <name> # display effective config |
46 | |
56 | |
47 | # debugging |
57 | # debugging |
48 | aemp trace <noderef> # trace the network topology |
58 | aemp trace <nodeid> # trace the network topology |
49 | |
59 | |
50 | =head1 DESCRIPTION |
60 | =head1 DESCRIPTION |
51 | |
61 | |
52 | With aemp you can configure various aspects of AnyEvent::MP and its |
62 | With aemp you can configure various aspects of AnyEvent::MP and its |
53 | protocol. |
63 | protocol. |
… | |
… | |
78 | : AE::cv ()->recv; |
88 | : AE::cv ()->recv; |
79 | } |
89 | } |
80 | } |
90 | } |
81 | |
91 | |
82 | use Carp (); |
92 | use Carp (); |
|
|
93 | |
|
|
94 | use JSON::XS; |
83 | |
95 | |
84 | use AnyEvent; |
96 | use AnyEvent; |
85 | use AnyEvent::Util; |
97 | use AnyEvent::Util; |
86 | |
98 | |
87 | use AnyEvent::MP; |
99 | use AnyEvent::MP; |
… | |
… | |
112 | } |
124 | } |
113 | |
125 | |
114 | our $cfg = AnyEvent::MP::Config::config; |
126 | our $cfg = AnyEvent::MP::Config::config; |
115 | our $profile = $cfg; |
127 | our $profile = $cfg; |
116 | |
128 | |
117 | sub resolve_port { |
|
|
118 | my ($node, $port) = split /#/, $_[0], 2; |
|
|
119 | |
|
|
120 | $node = (resolve_node $node)->recv; |
|
|
121 | "$node#$port" |
|
|
122 | } |
|
|
123 | |
|
|
124 | sub trace { |
129 | sub trace { |
125 | my ($node) = @_; |
130 | my ($node) = @_; |
126 | my $cv = AE::cv; |
131 | my $cv = AE::cv; |
127 | my %seen; |
132 | my %seen; |
128 | |
133 | |
129 | my $to = AE::timer 15, 0, sub { |
134 | my $to = AE::timer 15, 0, sub { |
130 | warn "timeout\n"; |
135 | warn "timeout\n"; |
131 | $cv->(); |
136 | $cv->(); |
132 | }; |
137 | }; |
133 | |
138 | |
134 | initialise_node "slave/", $node; |
139 | initialise_node "anon/", $node; |
135 | |
140 | |
136 | my $reply = port { |
141 | my $reply = port { |
137 | my ($node, @neigh) = @_; |
142 | my ($node, @neigh) = @_; |
138 | |
143 | |
139 | @neigh = grep $_ ne $NODE, @neigh; |
144 | @neigh = grep $_ ne $NODE, @neigh; |
… | |
… | |
158 | |
163 | |
159 | sub docmd; |
164 | sub docmd; |
160 | |
165 | |
161 | our %CMD = ( |
166 | our %CMD = ( |
162 | snd => sub { |
167 | snd => sub { |
163 | my $port = resolve_port shift @ARGV; |
168 | my $port = shift @ARGV; |
164 | initialise_node "slave/", node_of $port; |
169 | initialise_node "anon/", node_of $port; |
165 | |
170 | |
166 | snd $port, @ARGV; @ARGV = (); |
171 | snd $port, @ARGV; @ARGV = (); |
167 | |
172 | |
168 | my $cv = AE::cv; |
173 | my $cv = AE::cv; |
169 | my $to = AE::timer 5, 0, sub { $cv->("timeout") }; |
174 | my $to = AE::timer 5, 0, sub { $cv->("timeout") }; |
… | |
… | |
173 | |
178 | |
174 | print join " ", $cv->recv, "\n"; |
179 | print join " ", $cv->recv, "\n"; |
175 | }, |
180 | }, |
176 | |
181 | |
177 | rpc => sub { |
182 | rpc => sub { |
178 | my $port = resolve_port shift @ARGV; |
183 | my $port = shift @ARGV; |
179 | initialise_node "slave/", node_of $port; |
184 | initialise_node "anon/", node_of $port; |
180 | |
185 | |
181 | my $cv = AE::cv; |
186 | my $cv = AE::cv; |
182 | my $to = AE::timer 5, 0, sub { $cv->("timeout") }; |
187 | my $to = AE::timer 5, 0, sub { $cv->("timeout") }; |
183 | my $reply = port { &$cv; 1 }; |
188 | my $reply = port { &$cv; 1 }; |
184 | snd $port, @ARGV, $reply; @ARGV = (); |
189 | snd $port, @ARGV, $reply; @ARGV = (); |
… | |
… | |
186 | |
191 | |
187 | print join " ", $cv->recv, "\n"; |
192 | print join " ", $cv->recv, "\n"; |
188 | }, |
193 | }, |
189 | |
194 | |
190 | mon => sub { |
195 | mon => sub { |
191 | my $port = resolve_port shift @ARGV; |
196 | my $port = shift @ARGV; |
192 | initialise_node "slave/", node_of $port; |
197 | initialise_node "anon/", node_of $port; |
193 | |
198 | |
194 | mon $port, my $cv = AE::cv; |
199 | mon $port, my $cv = AE::cv; |
195 | print join " ", $cv->recv, "\n"; |
200 | print join " ", $cv->recv, "\n"; |
196 | }, |
201 | }, |
197 | |
202 | |
198 | trace => sub { |
203 | trace => sub { |
199 | @ARGV >= 1 |
204 | @ARGV >= 1 |
200 | or die "noderef missing\n"; |
205 | or die "node id missing\n"; |
201 | |
206 | |
202 | trace +(resolve_node shift @ARGV)->recv; |
207 | trace shift @ARGV; |
203 | }, |
208 | }, |
204 | |
209 | |
205 | setnoderef => sub { |
210 | setnodeid => sub { |
206 | @ARGV >= 1 |
211 | @ARGV >= 1 |
207 | or die "shared secret missing\n"; |
212 | or die "shared secret missing\n"; |
208 | |
213 | |
209 | $profile->{noderef} = shift @ARGV; |
214 | $profile->{nodeid} = shift @ARGV; |
210 | ++$cfg->{dirty}; |
215 | ++$cfg->{dirty}; |
211 | }, |
216 | }, |
212 | clrnoderef => sub { |
217 | delnodeid => sub { |
213 | delete $profile->{noderef}; |
218 | delete $profile->{nodeid}; |
214 | ++$cfg->{dirty}; |
219 | ++$cfg->{dirty}; |
215 | }, |
220 | }, |
216 | |
221 | |
217 | setsecret => sub { |
222 | setsecret => sub { |
218 | @ARGV >= 1 |
223 | @ARGV >= 1 |
… | |
… | |
223 | }, |
228 | }, |
224 | gensecret => sub { |
229 | gensecret => sub { |
225 | $profile->{secret} = AnyEvent::MP::Base::asciibits AnyEvent::MP::Base::nonce 64; |
230 | $profile->{secret} = AnyEvent::MP::Base::asciibits AnyEvent::MP::Base::nonce 64; |
226 | ++$cfg->{dirty}; |
231 | ++$cfg->{dirty}; |
227 | }, |
232 | }, |
228 | clrsecret => sub { |
233 | delsecret => sub { |
229 | delete $profile->{secret}; |
234 | delete $profile->{secret}; |
230 | ++$cfg->{dirty}; |
235 | ++$cfg->{dirty}; |
231 | }, |
236 | }, |
232 | |
237 | |
233 | setcert => sub { |
238 | setcert => sub { |
… | |
… | |
243 | }, |
248 | }, |
244 | gencert => sub { |
249 | gencert => sub { |
245 | $profile->{cert} = gen_cert; |
250 | $profile->{cert} = gen_cert; |
246 | ++$cfg->{dirty}; |
251 | ++$cfg->{dirty}; |
247 | }, |
252 | }, |
248 | clrcert => sub { |
253 | delcert => sub { |
249 | delete $profile->{cert}; |
254 | delete $profile->{cert}; |
|
|
255 | ++$cfg->{dirty}; |
|
|
256 | }, |
|
|
257 | |
|
|
258 | setbinds => sub { |
|
|
259 | $profile->{binds} = [@ARGV]; |
|
|
260 | @ARGV = (); |
|
|
261 | ++$cfg->{dirty}; |
|
|
262 | }, |
|
|
263 | delbinds => sub { |
|
|
264 | delete $profile->{binds}; |
|
|
265 | ++$cfg->{dirty}; |
|
|
266 | }, |
|
|
267 | addbind => sub { |
|
|
268 | @ARGV >= 1 |
|
|
269 | or die "bind address missing\n"; |
|
|
270 | my $bind = shift @ARGV; |
|
|
271 | |
|
|
272 | @{ $profile->{binds} } = grep $_ ne $bind, @{ $profile->{binds} }; |
|
|
273 | push @{ $profile->{binds} }, $bind; |
|
|
274 | ++$cfg->{dirty}; |
|
|
275 | }, |
|
|
276 | delbind => sub { |
|
|
277 | @ARGV >= 1 |
|
|
278 | or die "bind address missing\n"; |
|
|
279 | my $bind = shift @ARGV; |
|
|
280 | |
|
|
281 | @{ $profile->{binds} } = grep $_ ne $bind, @{ $profile->{binds} }; |
250 | ++$cfg->{dirty}; |
282 | ++$cfg->{dirty}; |
251 | }, |
283 | }, |
252 | |
284 | |
253 | setseeds => sub { |
285 | setseeds => sub { |
254 | $profile->{seeds} = [@ARGV]; |
286 | $profile->{seeds} = [@ARGV]; |
255 | @ARGV = (); |
287 | @ARGV = (); |
256 | ++$cfg->{dirty}; |
288 | ++$cfg->{dirty}; |
257 | }, |
289 | }, |
|
|
290 | delseeds => sub { |
|
|
291 | delete $profile->{seeds}; |
|
|
292 | ++$cfg->{dirty}; |
|
|
293 | }, |
258 | addseed => sub { |
294 | addseed => sub { |
259 | @ARGV >= 1 |
295 | @ARGV >= 1 |
260 | or die "seed noderef missing\n"; |
296 | or die "seed address missing\n"; |
261 | my $seed = shift @ARGV; |
297 | my $seed = shift @ARGV; |
262 | |
298 | |
263 | @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} }; |
299 | @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} }; |
264 | push @{ $profile->{seeds} }, $seed; |
300 | push @{ $profile->{seeds} }, $seed; |
265 | ++$cfg->{dirty}; |
301 | ++$cfg->{dirty}; |
266 | }, |
302 | }, |
267 | delseed => sub { |
303 | delseed => sub { |
268 | @ARGV >= 1 |
304 | @ARGV >= 1 |
269 | or die "seed noderef missing\n"; |
305 | or die "seed address missing\n"; |
270 | my $seed = shift @ARGV; |
306 | my $seed = shift @ARGV; |
271 | |
307 | |
272 | @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} }; |
308 | @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} }; |
273 | ++$cfg->{dirty}; |
309 | ++$cfg->{dirty}; |
274 | }, |
310 | }, |
275 | |
311 | |
276 | setservices => sub { |
312 | setservices => sub { |
277 | $profile->{services} = [@ARGV]; |
313 | $profile->{services} = [@ARGV]; |
278 | @ARGV = (); |
314 | @ARGV = (); |
|
|
315 | ++$cfg->{dirty}; |
|
|
316 | }, |
|
|
317 | delservices => sub { |
|
|
318 | delete $profile->{services}; |
279 | ++$cfg->{dirty}; |
319 | ++$cfg->{dirty}; |
280 | }, |
320 | }, |
281 | addservice => sub { |
321 | addservice => sub { |
282 | @ARGV >= 1 |
322 | @ARGV >= 1 |
283 | or die "service specification missing\n"; |
323 | or die "service specification missing\n"; |
… | |
… | |
313 | my $name = shift @ARGV; |
353 | my $name = shift @ARGV; |
314 | |
354 | |
315 | delete $cfg->{profile}{$name}; |
355 | delete $cfg->{profile}{$name}; |
316 | ++$cfg->{dirty}; |
356 | ++$cfg->{dirty}; |
317 | }, |
357 | }, |
|
|
358 | showprofile => sub { |
|
|
359 | @ARGV >= 1 |
|
|
360 | or die "profile name is missing\n"; |
|
|
361 | my $name = shift @ARGV; |
|
|
362 | |
|
|
363 | print JSON::XS->new->pretty->encode ($cfg->{profile}{$name} || {}); |
|
|
364 | }, |
|
|
365 | showconfig => sub { |
|
|
366 | my $name = @ARGV ? shift @ARGV : AnyEvent::MP::Kernel::_nodename; |
|
|
367 | |
|
|
368 | print JSON::XS->new->pretty->encode (AnyEvent::MP::Config::find_profile $name); |
|
|
369 | }, |
318 | ); |
370 | ); |
319 | |
371 | |
320 | sub docmd { |
372 | sub docmd { |
321 | my $cmd = shift @ARGV; |
373 | my $cmd = shift @ARGV; |
322 | |
374 | |