File Coverage

blib/lib/Protocol/DBus/Peer.pm
Criterion Covered Total %
statement 57 76 75.0
branch 6 16 37.5
condition 7 11 63.6
subroutine 13 20 65.0
pod 8 12 66.6
total 91 135 67.4


line stmt bran cond sub pod time code
1             package Protocol::DBus::Peer;
2              
3 5     5   2190 use strict;
  5         14  
  5         136  
4 5     5   28 use warnings;
  5         7  
  5         158  
5              
6             =encoding utf-8
7              
8             =head1 NAME
9              
10             Protocol::DBus::Peer - base class for a D-Bus peer
11              
12             =head1 SYNOPSIS
13              
14             $dbus->send_call(
15             interface => 'org.freedesktop.DBus.Properties',
16             member => 'GetAll',
17             signature => 's',
18             path => '/org/freedesktop/DBus',
19             destination => 'org.freedesktop.DBus',
20             body => [ 'org.freedesktop.DBus' ],
21             on_return => sub { my ($msg) = @_ },
22             );
23              
24             my $msg = $dbus->get_message();
25              
26             # Same pattern as the IO::Handle method.
27             $dbus->blocking(0);
28              
29             my $fileno = $dbus->fileno();
30              
31             $dbus->flush_write_queue() if $dbus->pending_send();
32              
33             # I’m not sure why you’d want to do this, but …
34             $dbus->big_endian();
35              
36             =head1 DESCRIPTION
37              
38             This class contains D-Bus logic that is useful in both client and
39             server contexts. (Currently this distribution does not include a server
40             implementation.)
41              
42             =cut
43              
44 5     5   2084 use Call::Context;
  5         1788  
  5         146  
45              
46 5     5   2191 use Protocol::DBus::Message;
  5         15  
  5         201  
47 5     5   2175 use Protocol::DBus::Parser;
  5         14  
  5         144  
48 5     5   2029 use Protocol::DBus::WriteMsg;
  5         18  
  5         4454  
49              
50             #----------------------------------------------------------------------
51              
52             =head1 METHODS
53              
54             =head2 $msg = I->get_message()
55              
56             This returns a single instace of L, or undef if
57             no message is available. It will also fire the appropriate “on_return”
58             method on METHOD_RETURN messages.
59              
60             The backend I/O logic reads data in chunks; thus, if there is a message
61             already available in the read buffer, no I/O is done. If you’re doing
62             non-blocking I/O then it is thus B that, every time the DBus socket
63             is readable, you call this function until undef is returned.
64              
65             =cut
66              
67             sub get_message {
68 3     3 1 38 my $msg = $_[0]->{'_parser'}->get_message();
69              
70 3 50       8 if ($msg) {
71 3 100       15 if (my $serial = $msg->get_header('REPLY_SERIAL')) {
72 1 50       5 if (my $cb = delete $_[0]->{'_on_return'}{$serial}) {
73 1         5 $cb->($msg);
74             }
75             }
76             }
77              
78 3         15 return $msg;
79             }
80              
81             #----------------------------------------------------------------------
82              
83             =head2 I->flush_write_queue()
84              
85             Same as L’s method of the same name.
86              
87             =cut
88              
89             sub flush_write_queue {
90 0 0   0 1 0 if ($_[0]->{'_io'}->get_write_queue_count()) {
91 0         0 return $_[0]->{'_io'}->flush_write_queue();
92             }
93              
94 0         0 return 1;
95             }
96              
97             #----------------------------------------------------------------------
98              
99             =head2 I->send_call( %OPTS )
100              
101             Send a METHOD_CALL message to the server.
102              
103             %OPTS are C, C, C, C, C,
104             C, and C. These do as you’d expect, with the following
105             caveats:
106              
107             =over
108              
109             =item * C, if given, must be an array reference. See
110             L for a discussion of how to map between D-Bus and
111             Perl.
112              
113             =item * The C callback receives the server’s response
114             message (NB: either METHOD_RETURN or ERROR) as argument.
115              
116             =back
117              
118             =cut
119              
120             sub send_call {
121 1     1 1 34 my ($self, %opts) = @_;
122              
123 1         4 my $cb = delete $opts{'on_return'};
124              
125 1         18 my $ret = $self->_send_msg(
126             %opts,
127             type => 'METHOD_CALL',
128             );
129              
130 1 50       50 if ($cb) {
131 1         3 my $serial = $self->{'_last_sent_serial'};
132 1         3 $self->{'_on_return'}{$serial} = $cb;
133             }
134              
135 1         7 return $ret;
136             }
137              
138             sub send_return {
139 1     1 0 49 my ($self, $orig_msg, @opts_kv) = @_;
140              
141 1         6 return $self->_send_msg(
142             @opts_kv,
143             reply_serial => $orig_msg->get_serial(),
144             type => 'METHOD_RETURN',
145             );
146             }
147              
148             sub send_error {
149 0     0 0 0 my ($self, $orig_msg, @opts_kv) = @_;
150              
151 0         0 return $self->_send_msg(
152             @opts_kv,
153             reply_serial => $orig_msg->get_serial(),
154             type => 'ERROR',
155             );
156             }
157              
158             sub send_signal {
159 1     1 0 1133 my ($self, @opts_kv) = @_;
160              
161 1         14 return $self->_send_msg(
162             @opts_kv,
163             type => 'SIGNAL',
164             );
165             }
166              
167             #----------------------------------------------------------------------
168              
169             =head2 I->big_endian()
170              
171             Same interface as C, but this sets/gets/toggles whether to send
172             big-endian messages instead of little-endian.
173              
174             (I’m not sure why it would matter?)
175              
176             =cut
177              
178             sub big_endian {
179 0     0 1 0 my ($self) = @_;
180              
181 0 0       0 if (@_ > 0) {
182 0         0 my $old = $self->{'_big_endian'};
183 0         0 $self->{'_big_endian'} = !!$_[1];
184              
185 0 0       0 $self->{'_to_str_fn'} = 'to_string_' . ($_[1] ? 'be' : 'le');
186              
187 0         0 return $self->{'_big_endian'};
188             }
189              
190 0         0 return !!$self->{'_big_endian'};
191             }
192              
193             #----------------------------------------------------------------------
194              
195             =head2 I->preserve_variant_signatures()
196              
197             Same interface as C, but when this is enabled
198             variants are given as two-member array references ([ signature => value ]),
199             blessed as C instances.
200              
201             For most Perl applications this is probably counterproductive.
202              
203             =cut
204              
205             sub preserve_variant_signatures {
206 0     0 1 0 my $self = shift;
207              
208 0         0 return $self->{'_parser'}->preserve_variant_signatures(@_);
209             }
210              
211             #----------------------------------------------------------------------
212              
213             =head2 I->blocking()
214              
215             Same interface as L’s method of the same name.
216              
217             =cut
218              
219             sub blocking {
220 0     0 1 0 my $self = shift;
221              
222 0         0 return $self->{'_socket'}->blocking(@_);
223             }
224              
225             #----------------------------------------------------------------------
226              
227             =head2 I->fileno()
228              
229             Returns the connection socket’s file descriptor.
230              
231             =cut
232              
233             sub fileno {
234 0     0 1 0 return fileno $_[0]->{'_socket'};
235             }
236              
237             #----------------------------------------------------------------------
238              
239             =head2 I->pending_send()
240              
241             Returns a boolean that indicates whether there is data queued up to send
242             to the server.
243              
244             =cut
245              
246             sub pending_send {
247 0     0 1 0 return !!$_[0]->{'_io'}->get_write_queue_count();
248             }
249              
250             #----------------------------------------------------------------------
251              
252             # undocumented
253             sub new {
254 2     2 0 812431 my ($class, $socket) = @_;
255              
256 2         34 my $self = bless { _socket => $socket }, $class;
257              
258 2         57 $self->_set_up_peer_io( $socket );
259              
260 2         6 return $self;
261             }
262              
263             #----------------------------------------------------------------------
264              
265             sub _set_up_peer_io {
266 2     2   13 my ($self, $socket) = @_;
267              
268 2         145 $self->{'_io'} = Protocol::DBus::WriteMsg->new( $socket )->enable_write_queue();
269 2         147 $self->{'_parser'} = Protocol::DBus::Parser->new( $socket );
270              
271 2         14 return;
272             }
273              
274             sub _send_msg {
275 3     3   54 my ($self, %opts) = @_;
276              
277 3         18 my ($type, $body_ar, $flags) = delete @opts{'type', 'body', 'flags'};
278              
279             my @hargs = map {
280 3         14 my $k = $_;
  14         23  
281 14         24 $k =~ tr;
282 14         39 ( $k => $opts{$_} );
283             } keys %opts;
284              
285 3         18 my $serial = ++$self->{'_last_sent_serial'};
286              
287 3         53 my $msg = Protocol::DBus::Message->new(
288             type => $type,
289             hfields => \@hargs,
290             flags => $flags,
291             body => $body_ar,
292             serial => $serial,
293             );
294              
295 3   100     54 $self->{'_endian'} ||= 'le';
296 3   66     37 $self->{'_to_str_fn'} ||= "to_string_$self->{'_endian'}";
297              
298 3         46 my ($buf_sr, $fds_ar) = $msg->can($self->{'_to_str_fn'})->($msg);
299              
300 3 50 66     26 if ($fds_ar && @$fds_ar && !$self->supports_unix_fd()) {
      33        
301 0         0 die "Cannot send file descriptors without UNIX FD support!";
302             }
303              
304 3         18 $self->{'_io'}->enqueue_message( $buf_sr, $fds_ar );
305              
306 3         20 return $self->{'_io'}->flush_write_queue();
307             }
308              
309             1;