ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/bin/aemp
Revision: 1.14
Committed: Fri Aug 14 14:01:05 2009 UTC (14 years, 9 months ago) by root
Branch: MAIN
CVS Tags: rel-0_7
Changes since 1.13: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #!/opt/bin/perl
2
3 =head1 NAME
4
5 aemp - AnyEvent:MP utility
6
7 =head1 SYNOPSIS
8
9 aemp command args...
10
11 # protocol commands
12 aemp snd <port> <arg...> # send a message
13 aemp mon <port> # wait till port is killed
14 aemp rpc <port> <arg...> # send message, append reply
15
16 # run a node
17 aemp run initialise_args... # run a node
18
19 # node configuration: protocol endpoints
20 aemp setnoderef <noderef> # configure the real noderef
21 aemp clrnoderef # reset noderef to default
22
23 # node configuration: secret
24 aemp gensecret # generate a random shared secret
25 aemp setsecret <secret> # set the shared secret
26 aemp clrsecret # remove the secret
27
28 # node configuration: TLS
29 aemp setcert <file> # set a certificate (key.pem + certificate.pem)
30 aemp clrcert # remove certificate
31 aemp gencert # generate a random certificate
32
33 # node configuration: seed nodes for bootstrapping
34 aemp setseeds <noderef>... # set seednodes
35 aemp addseed <noderef> # add a seednode
36 aemp delseed <noderef> # remove seednode
37
38 # node configuration: services
39 aemp setservices initfunc... # set service functions
40 aemp addservice <initfunc> # add an instance of a service
41 aemp delservice <initfunc> # delete one instance of a service
42
43 # profile-specific configuration
44 aemp profile <name> <command>... # apply command to profile only
45 aemp delprofile <name> # eradicate the named profile
46
47 # debugging
48 aemp trace <noderef> # trace the network topology
49
50 =head1 DESCRIPTION
51
52 With aemp you can configure various aspects of AnyEvent::MP and its
53 protocol.
54
55 You can also start a "default node", a node that only depends on the
56 static configuration.
57
58 =cut
59
60 use common::sense;
61
62 BEGIN {
63 if ($ARGV[0] eq "run") {
64 shift;
65
66 # d'oh
67 eval "use AnyEvent::Watchdog qw(autorestart heartbeat=300)";
68
69 require AnyEvent;
70 require AnyEvent::MP;
71 AnyEvent::MP::initialise_node (@ARGV);
72
73 AnyEvent::detect () eq "AnyEvent::Impl::E"
74 ? EV::loop ()
75 : AE::cv ()->recv;
76 }
77 }
78
79 use Carp ();
80
81 use AnyEvent;
82 use AnyEvent::Util;
83
84 use AnyEvent::MP;
85 use AnyEvent::MP::Config;
86
87 sub my_run_cmd {
88 my ($cmd) = @_;
89
90 my $cv = &run_cmd;
91 my $status = $cv->recv;
92
93 $status
94 and die "@$cmd: command failed with exit status $status.";
95 }
96
97 sub gen_cert {
98 my_run_cmd [qw(openssl req
99 -new -nodes -x509 -days 3650
100 -newkey rsa:2048 -keyout /dev/fd/3
101 -batch -subj /CN=AnyEvent::MP
102 )],
103 "<", "/dev/null",
104 ">" , \my $cert,
105 "3>", \my $key,
106 "2>", "/dev/null";
107
108 "$cert$key"
109 }
110
111 our $cfg = AnyEvent::MP::Config::config;
112 our $profile = $cfg;
113
114 sub resolve_port {
115 my ($node, $port) = split /#/, $_[0], 2;
116
117 $node = (resolve_node $node)->recv;
118 "$node#$port"
119 }
120
121 sub trace {
122 my ($node) = @_;
123 my $cv = AE::cv;
124 my %seen;
125
126 my $to = AE::timer 15, 0, sub {
127 warn "timeout\n";
128 $cv->();
129 };
130
131 initialise_node "slave/", $node;
132
133 my $reply = port {
134 my ($node, @neigh) = @_;
135
136 @neigh = grep $_ ne $NODE, @neigh;
137
138 print +(join " ", $node, @neigh), "\n";
139
140 for (@neigh) {
141 unless ($seen{$_}++) {
142 $cv->begin;
143 snd $_, up_nodes => $SELF => $_;
144 }
145 }
146
147 $cv->end;
148 };
149
150 $cv->begin;
151 snd $reply, seed => $node;
152
153 $cv->recv;
154 }
155
156 sub docmd;
157
158 our %CMD = (
159 snd => sub {
160 my $port = resolve_port shift @ARGV;
161 initialise_node "slave/", node_of $port;
162
163 snd $port, @ARGV; @ARGV = ();
164
165 my $cv = AE::cv;
166 my $to = AE::timer 5, 0, sub { $cv->("timeout") };
167 mon $port, $cv;
168 my $reply = port { &$cv; 1 };
169 snd node_of $port, relay => $reply, "ok";
170
171 print join " ", $cv->recv, "\n";
172 },
173
174 rpc => sub {
175 my $port = resolve_port shift @ARGV;
176 initialise_node "slave/", node_of $port;
177
178 my $cv = AE::cv;
179 my $to = AE::timer 5, 0, sub { $cv->("timeout") };
180 my $reply = port { &$cv; 1 };
181 snd $port, @ARGV, $reply; @ARGV = ();
182 mon $port, $cv;
183
184 print join " ", $cv->recv, "\n";
185 },
186
187 mon => sub {
188 my $port = resolve_port shift @ARGV;
189 initialise_node "slave/", node_of $port;
190
191 mon $port, my $cv = AE::cv;
192 print join " ", $cv->recv, "\n";
193 },
194
195 trace => sub {
196 @ARGV >= 1
197 or die "noderef missing\n";
198
199 trace +(resolve_node shift @ARGV)->recv;
200 },
201
202 setnoderef => sub {
203 @ARGV >= 1
204 or die "shared secret missing\n";
205
206 $profile->{noderef} = shift @ARGV;
207 ++$cfg->{dirty};
208 },
209 clrnoderef => sub {
210 delete $profile->{noderef};
211 ++$cfg->{dirty};
212 },
213
214 setsecret => sub {
215 @ARGV >= 1
216 or die "shared secret missing\n";
217
218 $profile->{secret} = shift @ARGV;
219 ++$cfg->{dirty};
220 },
221 gensecret => sub {
222 $profile->{secret} = AnyEvent::MP::Base::asciibits AnyEvent::MP::Base::nonce 64;
223 ++$cfg->{dirty};
224 },
225 clrsecret => sub {
226 delete $profile->{secret};
227 ++$cfg->{dirty};
228 },
229
230 setcert => sub {
231 @ARGV >= 1
232 or die "key+certificate pem filename missing\n";
233
234 open my $fh, "<", $ARGV[0]
235 or die "$ARGV[0]: $!";
236
237 local $/;
238 $profile->{cert} = <$fh>;
239 ++$cfg->{dirty};
240 },
241 gencert => sub {
242 $profile->{cert} = gen_cert;
243 ++$cfg->{dirty};
244 },
245 clrcert => sub {
246 delete $profile->{cert};
247 ++$cfg->{dirty};
248 },
249
250 setseeds => sub {
251 $profile->{seeds} = [@ARGV];
252 @ARGV = ();
253 ++$cfg->{dirty};
254 },
255 addseed => sub {
256 @ARGV >= 1
257 or die "seed noderef missing\n";
258 my $seed = shift @ARGV;
259
260 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
261 push @{ $profile->{seeds} }, $seed;
262 ++$cfg->{dirty};
263 },
264 delseed => sub {
265 @ARGV >= 1
266 or die "seed noderef missing\n";
267 my $seed = shift @ARGV;
268
269 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
270 ++$cfg->{dirty};
271 },
272
273 setservices => sub {
274 $profile->{services} = [@ARGV];
275 @ARGV = ();
276 ++$cfg->{dirty};
277 },
278 addservice => sub {
279 @ARGV >= 1
280 or die "service specification missing\n";
281 my $service = shift @ARGV;
282 push @{ $profile->{services} }, $service;
283 ++$cfg->{dirty};
284 },
285 delservice => sub {
286 @ARGV >= 1
287 or die "service specification missing\n";
288 my $service = shift @ARGV;
289 for (0 .. $#{ $profile->{services} }) {
290 next unless $profile->{services}[$_] eq $service;
291 splice @{ $profile->{services} }, $_, 1;
292 last;
293 }
294 ++$cfg->{dirty};
295 },
296
297 profile => sub {
298 @ARGV >= 2
299 or die "profile name or subcommand are missing\n";
300 my $name = shift @ARGV;
301
302 $profile = $cfg->{profile}{$name} ||= {};
303 ++$cfg->{dirty};
304
305 docmd;
306 },
307 delprofile => sub {
308 @ARGV >= 1
309 or die "profile name is missing\n";
310 my $name = shift @ARGV;
311
312 delete $cfg->{profile}{$name};
313 ++$cfg->{dirty};
314 },
315 );
316
317 sub docmd {
318 my $cmd = shift @ARGV;
319
320 $CMD{$cmd}
321 or die "$cmd: no such aemp command (try man aemp)";
322
323 $CMD{$cmd}();
324 }
325
326 @ARGV
327 or die "Usage: aemp subcommand ... (try man aemp)\n";
328
329 docmd;
330
331