ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/bin/aemp
Revision: 1.11
Committed: Thu Aug 13 22:32:41 2009 UTC (14 years, 9 months ago) by root
Branch: MAIN
Changes since 1.10: +42 -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 #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 print +(join " ", @_), "\n";
134
135 shift;
136 for (@_) {
137 unless ($seen{$_}++) {
138 $cv->begin;
139 snd $_, up_nodes => $SELF => $_;
140 }
141 }
142
143 $cv->end;
144 };
145
146 $cv->begin;
147 snd $reply, seed => $node;
148
149 $cv->recv;
150 }
151
152 sub docmd;
153
154 our %CMD = (
155 snd => sub {
156 my $port = resolve_port shift @ARGV;
157 initialise_node "slave/", node_of $port;
158
159 snd $port, @ARGV; @ARGV = ();
160
161 my $cv = AE::cv;
162 my $to = AE::timer 5, 0, sub { $cv->("timeout") };
163 mon $port, $cv;
164 my $reply = port { &$cv; 1 };
165 snd node_of $port, relay => $reply, "ok";
166
167 print join " ", $cv->recv, "\n";
168 },
169
170 rpc => sub {
171 my $port = resolve_port shift @ARGV;
172 initialise_node "slave/", node_of $port;
173
174 my $cv = AE::cv;
175 my $to = AE::timer 5, 0, sub { $cv->("timeout") };
176 my $reply = port { &$cv; 1 };
177 snd $port, @ARGV, $reply; @ARGV = ();
178 mon $port, $cv;
179
180 print join " ", $cv->recv, "\n";
181 },
182
183 mon => sub {
184 my $port = resolve_port shift @ARGV;
185 initialise_node "slave/", node_of $port;
186
187 mon $port, my $cv = AE::cv;
188 print join " ", $cv->recv, "\n";
189 },
190
191 trace => sub {
192 @ARGV >= 1
193 or die "noderef missing\n";
194
195 trace +(resolve_node shift @ARGV)->recv;
196 },
197
198 setnoderef => sub {
199 @ARGV >= 1
200 or die "shared secret missing\n";
201
202 $profile->{noderef} = shift @ARGV;
203 ++$cfg->{dirty};
204 },
205 clrnoderef => sub {
206 delete $profile->{noderef};
207 ++$cfg->{dirty};
208 },
209
210 setsecret => sub {
211 @ARGV >= 1
212 or die "shared secret missing\n";
213
214 $profile->{secret} = shift @ARGV;
215 ++$cfg->{dirty};
216 },
217 gensecret => sub {
218 $profile->{secret} = AnyEvent::MP::Base::asciibits AnyEvent::MP::Base::nonce 64;
219 ++$cfg->{dirty};
220 },
221 clrsecret => sub {
222 delete $profile->{secret};
223 ++$cfg->{dirty};
224 },
225
226 setcert => sub {
227 @ARGV >= 1
228 or die "key+certificate pem filename missing\n";
229
230 open my $fh, "<", $ARGV[0]
231 or die "$ARGV[0]: $!";
232
233 local $/;
234 $profile->{cert} = <$fh>;
235 ++$cfg->{dirty};
236 },
237 gencert => sub {
238 $profile->{cert} = gen_cert;
239 ++$cfg->{dirty};
240 },
241 clrcert => sub {
242 delete $profile->{cert};
243 ++$cfg->{dirty};
244 },
245
246 setseeds => sub {
247 $profile->{seeds} = [@ARGV];
248 @ARGV = ();
249 ++$cfg->{dirty};
250 },
251 addseed => sub {
252 @ARGV >= 1
253 or die "seed noderef missing\n";
254 my $seed = shift @ARGV;
255
256 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
257 push @{ $profile->{seeds} }, $seed;
258 ++$cfg->{dirty};
259 },
260 delseed => sub {
261 @ARGV >= 1
262 or die "seed noderef missing\n";
263 my $seed = shift @ARGV;
264
265 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
266 ++$cfg->{dirty};
267 },
268
269 setservices => sub {
270 $profile->{services} = [@ARGV];
271 @ARGV = ();
272 ++$cfg->{dirty};
273 },
274 addservice => sub {
275 @ARGV >= 1
276 or die "service specification missing\n";
277 my $service = shift @ARGV;
278 push @{ $profile->{services} }, $service;
279 ++$cfg->{dirty};
280 },
281 delservice => sub {
282 @ARGV >= 1
283 or die "service specification missing\n";
284 my $service = shift @ARGV;
285 for (0 .. $#{ $profile->{services} }) {
286 next unless $profile->{services}[$_] eq $service;
287 splice @{ $profile->{services} }, $_, 1;
288 last;
289 }
290 ++$cfg->{dirty};
291 },
292
293 profile => sub {
294 @ARGV >= 2
295 or die "profile name or subcommand are missing\n";
296 my $name = shift @ARGV;
297
298 $profile = $cfg->{profile}{$name} ||= {};
299
300 docmd;
301 },
302 delprofile => sub {
303 @ARGV >= 1
304 or die "profile name is missing\n";
305 my $name = shift @ARGV;
306
307 delete $cfg->{profile}{$name};
308 },
309 );
310
311 sub docmd {
312 my $cmd = shift @ARGV;
313
314 $CMD{$cmd}
315 or die "$cmd: no such aemp command (try man aemp)";
316
317 $CMD{$cmd}();
318 }
319
320 @ARGV
321 or die "Usage: aemp subcommand ... (try man aemp)\n";
322
323 docmd;
324
325