Imported Upstream version 3.3.1
[debian/amanda] / perl / Amanda / IPC / Binary.pm
1 # This file was automatically generated by SWIG (http://www.swig.org).
2 # Version 2.0.4
3 #
4 # Do not make changes to this file unless you know what you are doing--modify
5 # the SWIG interface file instead.
6
7 package Amanda::IPC::Binary;
8 use base qw(Exporter);
9 use base qw(DynaLoader);
10 package Amanda::IPC::Binaryc;
11 bootstrap Amanda::IPC::Binary;
12 package Amanda::IPC::Binary;
13 @EXPORT = qw();
14
15 # ---------- BASE METHODS -------------
16
17 package Amanda::IPC::Binary;
18
19 sub TIEHASH {
20     my ($classname,$obj) = @_;
21     return bless $obj, $classname;
22 }
23
24 sub CLEAR { }
25
26 sub FIRSTKEY { }
27
28 sub NEXTKEY { }
29
30 sub FETCH {
31     my ($self,$field) = @_;
32     my $member_func = "swig_${field}_get";
33     $self->$member_func();
34 }
35
36 sub STORE {
37     my ($self,$field,$newval) = @_;
38     my $member_func = "swig_${field}_set";
39     $self->$member_func($newval);
40 }
41
42 sub this {
43     my $ptr = shift;
44     return tied(%$ptr);
45 }
46
47
48 # ------- FUNCTION WRAPPERS --------
49
50 package Amanda::IPC::Binary;
51
52 *ipc_binary_proto_new = *Amanda::IPC::Binaryc::ipc_binary_proto_new;
53 *ipc_binary_proto_add_cmd = *Amanda::IPC::Binaryc::ipc_binary_proto_add_cmd;
54 *ipc_binary_cmd_add_arg = *Amanda::IPC::Binaryc::ipc_binary_cmd_add_arg;
55 *ipc_binary_new_channel = *Amanda::IPC::Binaryc::ipc_binary_new_channel;
56 *ipc_binary_free_channel = *Amanda::IPC::Binaryc::ipc_binary_free_channel;
57 *ipc_binary_read_message = *Amanda::IPC::Binaryc::ipc_binary_read_message;
58 *ipc_binary_write_message = *Amanda::IPC::Binaryc::ipc_binary_write_message;
59 *ipc_binary_feed_data = *Amanda::IPC::Binaryc::ipc_binary_feed_data;
60 *ipc_binary_data_transmitted = *Amanda::IPC::Binaryc::ipc_binary_data_transmitted;
61 *ipc_binary_poll_message = *Amanda::IPC::Binaryc::ipc_binary_poll_message;
62 *ipc_binary_queue_message = *Amanda::IPC::Binaryc::ipc_binary_queue_message;
63
64 # ------- VARIABLE STUBS --------
65
66 package Amanda::IPC::Binary;
67
68 *IPC_BINARY_STRING = *Amanda::IPC::Binaryc::IPC_BINARY_STRING;
69 *IPC_BINARY_OPTIONAL = *Amanda::IPC::Binaryc::IPC_BINARY_OPTIONAL;
70
71 @EXPORT_OK = ();
72 %EXPORT_TAGS = ();
73
74
75 =head1 NAME
76
77 Amanda::IPC::Binary - binary-framed message-based communication
78
79 =head1 SYNOPSIS
80
81 See below.
82
83 =head1 DESCRIPTION
84
85 This package is an interface to the C-level protocol library declared in
86 C<common-src/ipc-binary.h>.  It enables two-way message-based communication,
87 using a binary framing that permits direct inclusion of non-string data.
88
89 Unlike the line protocol (see L<Amanda::IPC::LineProtocol>), this package does
90 not yet support asynchronous operation.
91
92 =head2 DEFINING A PROTOCOL
93
94 There are two parts to any use of this package.  First, define the protocol by
95 creating a subclass and populating it.  This subclass represents the protocol,
96 composed of a set of commands or messages and arguments that are attached to
97 those commands.
98
99 Begin with the subclass:
100
101     package TestProtocol;
102     use base "Amanda::IPC::Binary";
103     use Amanda::IPC::Binary;
104
105 Then define the constants for each command.  Note that the C<constant> pragma did
106 not support the hash syntax in Perl-5.6, so this must be written as individual
107 invocations of the constant:
108
109     use constant CMD1 => 1;
110     use constant CMD2 => 2;
111
112 Then the constants for each argument:
113
114     use constant USERNAME => 1;
115     use constant PASSWORD => 2;
116     use constant RESOURCE => 3;
117     use constant USE_OVERDRIVE => 4;
118
119 Next, give the magic value for the protocol:
120
121     magic(0x9812);
122
123 Then begin defining each command, along with its arguments:
124
125     command(CMD1,
126         RESOURCE, 0,
127         USERNAME, $IPC_BINARY_STRING,
128         PASSWORD, $IPC_BINARY_STRING|$IPC_BINARY_OPTIONAL);
129
130 The first argument to C<command> specifies the command ID.  The remaining
131 arguments are taken in pairs, and specify the argument and a bitfield of
132 flags.  The available flags are:
133
134     $IPC_BINARY_STRING      argument is a printable string
135     $IPC_BINARY_OPTIONAL    argument is not required
136
137 If $IPC_BINARY_STRING is not specified, the argument can contain any sequence of
138 bytes (including nuls). In either case, a perl string is used to represent it.
139
140 =head2 USING A PROTOCOL
141
142 Once a protocol is defined, it forms a class which can be used to run the
143 protocol.  Multiple instances of this class can be created to handle
144 simultaneous uses of the protocol over different channels.
145
146 The constructor takes no parameters, but establishs a new channel, complete with
147 buffers for partially-read commands:
148
149     my $chan = TestProtocol->new();
150
151 To write a message, call the C<write_message> method, passing a filehandle, a
152 command id, and argument/value pairs:
153
154     if (!$chan->write_message($fh, TestProtocol::CMD1,
155             TestProtocol::RESOURCE => $res,
156             TestProtocol::USERNAME => "dustin")) {
157         # ...
158     }
159
160 It is not valid to omit an argument value, and all values must be perl strings
161 -- C<undef> is not alloewd, even for optional arguments.  If C<write_message>
162 fails, it returns false and C<$!> is set appropriately.  The function does not
163 return until the message has been written to the file.
164
165 To read a message, call C<read_message>, again passing a filehandle:
166
167     my $msg = $chan->read_message($fh);
168
169 Note that this will block until a full message has been read.  The resulting
170 message object has a C<cmd_id> key that identifies the command and an C<args>
171 key that references a list of argument values, keyed by their argument ID:
172
173     if ($msg->{'cmd_id'} == TestProtocol::CMD2) { ... }
174     print $msg->{'args'}[TestProtocol::USERNAME], "\n";
175
176 The C<close> method will flush any open buffers and close a channel.  In the
177 synchronous case, this is essentially a no-op since all output buffers are
178 flushed at each call to C<write_message>.
179
180 =cut
181
182
183 push @EXPORT, qw($IPC_BINARY_STRING $IPC_BINARY_OPTIONAL);
184
185
186 use Carp;
187 push @EXPORT, qw( magic command new message );
188
189 # a map from package name to protocol
190 my %protos_by_pkg;
191
192 sub magic {
193     my ($magic) = @_;
194     my $caller = caller;
195
196     croak "magic already set for this protocol"
197         if (exists $protos_by_pkg{$caller});
198
199     $protos_by_pkg{$caller} = ipc_binary_proto_new($magic);
200 }
201
202 sub command {
203     my ($cmd_id, @args) = @_;
204     my $caller = caller;
205
206     croak "magic not set for this protocol"
207         unless (exists $protos_by_pkg{$caller});
208
209     croak "command args must be specified in pairs"
210         unless (@args % 2 == 0);
211
212     my $proto = $protos_by_pkg{$caller};
213     $cmd = ipc_binary_proto_add_cmd($proto, $cmd_id);
214
215     while (@args) {
216         my $arg = shift @args;
217         my $flags = shift @args;
218         ipc_binary_cmd_add_arg($cmd, $arg, $flags);
219     }
220 }
221
222 ##
223 # Class Methods
224
225 sub new {
226     my $class = shift;
227
228     my $self = bless {
229         chan => ipc_binary_new_channel($protos_by_pkg{$class}),
230     }, $class;
231 }
232
233 sub message {
234     my $self = shift;
235     my ($cmd_id, @args) = @_;
236
237     $self = bless {
238         cmd_id => $cmd_id,
239         chan => $self->{'chan'},
240         args => [],
241     }, "Amanda::IPC::Binary::Message";
242
243
244     while (@args) {
245         my $arg = shift @args;
246         my $val = shift @args;
247         $self->{'args'}[$arg] = $val;
248     }
249
250     return $self;
251 }
252
253 sub close {
254     if ($self->{'chan'}) {
255         ipc_binary_free_channel($self->{'chan'});
256         $self->{'chan'} = undef;
257     }
258 }
259
260 *DESTROY = *close;
261
262 ##
263 # Blocking interface
264
265 sub read_message {
266     my $self = shift;
267     my ($fd) = @_;
268
269     return ipc_binary_read_message($self->{'chan'}, $fd);
270 }
271
272 sub write_message {
273     my $self = shift;
274     my ($fd, $msg) = @_;
275
276     if (ipc_binary_write_message($self->{'chan'}, $fd, $msg) < 0) {
277         return 0;
278     }
279     return 1;
280 }
281
282 ##
283 # Nonblocking interface -- TODO
284
285 ##
286 # Message structure
287
288 package Amanda::IPC::Binary::Message;
289
290 # (constructor is the protocol's C<message> method)
291
292 # format:
293 # { cmd_id => $cmd_id,
294 #   chan => $channel,
295 #   args => [ $arg0, $arg1, .. ],
296 # }
297
298 sub get_cmd {
299     return $self->{'cmd_id'};
300 }
301
302 sub get_arg {
303     my ($self, $arg_id) = @_;
304
305     return $self->{'args'}[$arg_id];
306 }
307
308 sub set_arg {
309     my ($self, $arg_id, $value) = @_;
310     $self->{'args'}[$arg_id] = $value;
311 }
312
313 package Amanda::IPC::Binary;
314
315 1;