ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/bin/aemp
Revision: 1.12
Committed: Thu Aug 13 22:43:38 2009 UTC (14 years, 9 months ago) by root
Branch: MAIN
Changes since 1.11: +6 -3 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 #TODO: watchdog? how?
67 #require AnyEvent::Watchdog;
68 require AnyEvent;
69 require AnyEvent::MP;
70 AnyEvent::MP::initialise_node (@ARGV);
71
72 AnyEvent::detect () eq "AnyEvent::Impl::E"
73 ? EV::loop ()
74 : AE::cv ()->recv;
75 }
76 }
77
78 use Carp ();
79
80 use AnyEvent;
81 use AnyEvent::Util;
82
83 use AnyEvent::MP;
84 use AnyEvent::MP::Config;
85
86 sub my_run_cmd {
87 my ($cmd) = @_;
88
89 my $cv = &run_cmd;
90 my $status = $cv->recv;
91
92 $status
93 and die "@$cmd: command failed with exit status $status.";
94 }
95
96 sub gen_cert {
97 my_run_cmd [qw(openssl req
98 -new -nodes -x509 -days 3650
99 -newkey rsa:2048 -keyout /dev/fd/3
100 -batch -subj /CN=AnyEvent::MP
101 )],
102 "<", "/dev/null",
103 ">" , \my $cert,
104 "3>", \my $key,
105 "2>", "/dev/null";
106
107 "$cert$key"
108 }
109
110 our $cfg = AnyEvent::MP::Config::config;
111 our $profile = $cfg;
112
113 sub resolve_port {
114 my ($node, $port) = split /#/, $_[0], 2;
115
116 $node = (resolve_node $node)->recv;
117 "$node#$port"
118 }
119
120 sub trace {
121 my ($node) = @_;
122 my $cv = AE::cv;
123 my %seen;
124
125 my $to = AE::timer 15, 0, sub {
126 warn "timeout\n";
127 $cv->();
128 };
129
130 initialise_node "slave/", $node;
131
132 my $reply = port {
133 my ($node, @neigh) = @_;
134
135 @neigh = grep $_ ne $NODE, @neigh;
136
137 print +(join " ", $node, @neigh), "\n";
138
139 for (@neigh) {
140 unless ($seen{$_}++) {
141 $cv->begin;
142 snd $_, up_nodes => $SELF => $_;
143 }
144 }
145
146 $cv->end;
147 };
148
149 $cv->begin;
150 snd $reply, seed => $node;
151
152 $cv->recv;
153 }
154
155 sub docmd;
156
157 our %CMD = (
158 snd => sub {
159 my $port = resolve_port shift @ARGV;
160 initialise_node "slave/", node_of $port;
161
162 snd $port, @ARGV; @ARGV = ();
163
164 my $cv = AE::cv;
165 my $to = AE::timer 5, 0, sub { $cv->("timeout") };
166 mon $port, $cv;
167 my $reply = port { &$cv; 1 };
168 snd node_of $port, relay => $reply, "ok";
169
170 print join " ", $cv->recv, "\n";
171 },
172
173 rpc => sub {
174 my $port = resolve_port shift @ARGV;
175 initialise_node "slave/", node_of $port;
176
177 my $cv = AE::cv;
178 my $to = AE::timer 5, 0, sub { $cv->("timeout") };
179 my $reply = port { &$cv; 1 };
180 snd $port, @ARGV, $reply; @ARGV = ();
181 mon $port, $cv;
182
183 print join " ", $cv->recv, "\n";
184 },
185
186 mon => sub {
187 my $port = resolve_port shift @ARGV;
188 initialise_node "slave/", node_of $port;
189
190 mon $port, my $cv = AE::cv;
191 print join " ", $cv->recv, "\n";
192 },
193
194 trace => sub {
195 @ARGV >= 1
196 or die "noderef missing\n";
197
198 trace +(resolve_node shift @ARGV)->recv;
199 },
200
201 setnoderef => sub {
202 @ARGV >= 1
203 or die "shared secret missing\n";
204
205 $profile->{noderef} = shift @ARGV;
206 ++$cfg->{dirty};
207 },
208 clrnoderef => sub {
209 delete $profile->{noderef};
210 ++$cfg->{dirty};
211 },
212
213 setsecret => sub {
214 @ARGV >= 1
215 or die "shared secret missing\n";
216
217 $profile->{secret} = shift @ARGV;
218 ++$cfg->{dirty};
219 },
220 gensecret => sub {
221 $profile->{secret} = AnyEvent::MP::Base::asciibits AnyEvent::MP::Base::nonce 64;
222 ++$cfg->{dirty};
223 },
224 clrsecret => sub {
225 delete $profile->{secret};
226 ++$cfg->{dirty};
227 },
228
229 setcert => sub {
230 @ARGV >= 1
231 or die "key+certificate pem filename missing\n";
232
233 open my $fh, "<", $ARGV[0]
234 or die "$ARGV[0]: $!";
235
236 local $/;
237 $profile->{cert} = <$fh>;
238 ++$cfg->{dirty};
239 },
240 gencert => sub {
241 $profile->{cert} = gen_cert;
242 ++$cfg->{dirty};
243 },
244 clrcert => sub {
245 delete $profile->{cert};
246 ++$cfg->{dirty};
247 },
248
249 setseeds => sub {
250 $profile->{seeds} = [@ARGV];
251 @ARGV = ();
252 ++$cfg->{dirty};
253 },
254 addseed => sub {
255 @ARGV >= 1
256 or die "seed noderef missing\n";
257 my $seed = shift @ARGV;
258
259 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
260 push @{ $profile->{seeds} }, $seed;
261 ++$cfg->{dirty};
262 },
263 delseed => sub {
264 @ARGV >= 1
265 or die "seed noderef missing\n";
266 my $seed = shift @ARGV;
267
268 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
269 ++$cfg->{dirty};
270 },
271
272 setservices => sub {
273 $profile->{services} = [@ARGV];
274 @ARGV = ();
275 ++$cfg->{dirty};
276 },
277 addservice => sub {
278 @ARGV >= 1
279 or die "service specification missing\n";
280 my $service = shift @ARGV;
281 push @{ $profile->{services} }, $service;
282 ++$cfg->{dirty};
283 },
284 delservice => sub {
285 @ARGV >= 1
286 or die "service specification missing\n";
287 my $service = shift @ARGV;
288 for (0 .. $#{ $profile->{services} }) {
289 next unless $profile->{services}[$_] eq $service;
290 splice @{ $profile->{services} }, $_, 1;
291 last;
292 }
293 ++$cfg->{dirty};
294 },
295
296 profile => sub {
297 @ARGV >= 2
298 or die "profile name or subcommand are missing\n";
299 my $name = shift @ARGV;
300
301 $profile = $cfg->{profile}{$name} ||= {};
302
303 docmd;
304 },
305 delprofile => sub {
306 @ARGV >= 1
307 or die "profile name is missing\n";
308 my $name = shift @ARGV;
309
310 delete $cfg->{profile}{$name};
311 },
312 );
313
314 sub docmd {
315 my $cmd = shift @ARGV;
316
317 $CMD{$cmd}
318 or die "$cmd: no such aemp command (try man aemp)";
319
320 $CMD{$cmd}();
321 }
322
323 @ARGV
324 or die "Usage: aemp subcommand ... (try man aemp)\n";
325
326 docmd;
327
328