File Coverage

blib/lib/RPC/PlClient.pm
Criterion Covered Total %
statement 106 109 97.2
branch 27 48 56.2
condition 5 10 50.0
subroutine 16 17 94.1
pod 3 4 75.0
total 157 188 83.5


line stmt bran cond sub pod time code
1             # -*- perl -*-
2             #
3             #
4             # PlRPC - Perl RPC, package for writing simple, RPC like clients and
5             # servers
6             #
7             # RPC::PlClient.pm is the module for writing the PlRPC client.
8             #
9             #
10             # Copyright (c) 1997, 1998 Jochen Wiedmann
11             #
12             # You may distribute under the terms of either the GNU General Public
13             # License or the Artistic License, as specified in the Perl README file.
14             #
15             # Author: Jochen Wiedmann
16             # Email: jochen.wiedmann at freenet.de
17             #
18              
19 4     4   597586 use strict;
  4         11  
  4         139  
20              
21 4     4   2290 use RPC::PlClient::Comm ();
  4         12  
  4         126  
22 4     4   33 use Net::Daemon::Log ();
  4         9  
  4         128  
23 4     4   25 use IO::Socket ();
  4         8  
  4         3295  
24              
25              
26             package RPC::PlClient;
27              
28             $RPC::PlClient::VERSION = '0.2020';
29             @RPC::PlClient::ISA = qw(Net::Daemon::Log);
30              
31              
32             ############################################################################
33             #
34             # Name: new
35             #
36             # Purpose: Constructor of the PlRPC::Client module
37             #
38             # Inputs: $self - Class name
39             # @attr - Attribute list
40             #
41             # Returns: Client object; dies in case of errors.
42             #
43             ############################################################################
44              
45             sub new ($@) {
46 5     5 1 6234231 my $proto = shift;
47 5         125 my $self = {@_};
48 5   33     102 bless($self, (ref($proto) || $proto));
49              
50 5         126 my $comm = $self->{'comm'} = RPC::PlClient::Comm->new($self);
51 5 50       27 my $app = $self->{'application'} or
52             $self->Fatal("Missing application name");
53 5 50       31 my $version = $self->{'version'} or
54             $self->Fatal("Missing version number");
55 5   100     42 my $user = $self->{'user'} || '';
56 5   50     44 my $password = $self->{'password'} || '';
57              
58 5         10 my $socket;
59 5 50       21 if (!($socket = $self->{'socket'})) {
60 5 50       18 $self->Fatal("Missing peer address") unless $self->{'peeraddr'};
61 5 50 33     33 $self->Fatal("Missing peer port")
62             unless ($self->{'peerport'} ||
63             index($self->{'peeraddr'}, ':') != -1);
64 5         4385 $socket = $self->{'socket'} = IO::Socket::INET->new
65             ('PeerAddr' => $self->{'peeraddr'},
66             'PeerPort' => $self->{'peerport'},
67             'Proto' => $self->{'socket_proto'},
68             'Type' => $self->{'socket_type'},
69             'Timeout' => $self->{'timeout'});
70 5 50       31402 $self->Fatal("Cannot connect: $!") unless $socket;
71             }
72 5         50 $self->Debug("Connected to %s, port %s",
73             $socket->peerhost(), $socket->peerport());
74 5         84900 $self->Debug("Sending login message: %s, %s, %s, %s",
75             $app, $version, $user, "x" x length($password));
76 5         922 $comm->Write($socket, [$app, $version, $user, $password]);
77 5         3365 $self->Debug("Waiting for server's response ...");
78 5         932 my $reply = $comm->Read($socket);
79 5 50       151 die "Unexpected EOF from server" unless defined($reply);
80 5 50       18 die "Expected server to return an array ref" unless ref($reply) eq 'ARRAY';
81 5 50       22 my $msg = defined($reply->[1]) ? $reply->[1] : '';
82 5 50       30 die "Refused by server: $msg" unless $reply->[0];
83 5         29 $self->Debug("Logged in, server replies: $msg");
84              
85 5 100       792 return ($self, $msg) if wantarray;
86 4         41 $self;
87             }
88              
89              
90             ############################################################################
91             #
92             # Name: Call
93             #
94             # Purpose: Coerce method located on the server
95             #
96             # Inputs: $self - client instance
97             # $method - method name
98             # @args - method attributes
99             #
100             # Returns: method results; dies in case of errors.
101             #
102             ############################################################################
103              
104             sub Call ($@) {
105 37     37 1 57 my $self = shift;
106 37         67 my $socket = $self->{'socket'};
107 37         60 my $comm = $self->{'comm'};
108 37         177 $comm->Write($socket, [@_]);
109 37         25601 my $msg = $comm->Read($socket);
110 37 50       955 die "Unexpected EOF while waiting for server reply" unless defined($msg);
111 37 100       417 die "Server returned error: $$msg" if ref($msg) eq 'SCALAR';
112 23 50       57 die "Expected server to return an array ref" unless ref($msg) eq 'ARRAY';
113 23         965 @$msg;
114             }
115              
116             sub ClientObject {
117 4     4 1 8 my $client = shift; my $class = shift; my $method = shift;
  4         29  
  4         8  
118 4         19 my($object) = $client->Call('NewHandle', $class, $method, @_);
119 4 50       13 die "Constructor didn't return a TRUE value" unless $object;
120 4 50       43 die "Constructor didn't return an object"
121             unless $object =~ /^((?:\w+|\:\:)+)=(\w+)/;
122 4         43 RPC::PlClient::Object->new($1, $client, $object);
123             }
124              
125             sub Disconnect {
126 0     0 0 0 my $self = shift;
127 0         0 $self->{'socket'} = undef;
128 0         0 1;
129             }
130              
131              
132             package RPC::PlClient::Object;
133              
134 4     4   26 use vars qw($AUTOLOAD);
  4         15  
  4         800  
135              
136             sub AUTOLOAD {
137 13     13   500 my $method = $AUTOLOAD;
138 13         68 my $index;
139 13 50       43 die "Cannot parse method: $method"
140             unless ($index = rindex($method, '::')) != -1;
141 13         30 my $class = substr($method, 0, $index);
142 13         5732 $method = substr($method, $index+2);
143 13 50   5   2760 eval <<"EOM";
  5 50   12   73  
  5 50   4   34  
  5 50   8   10  
  5         24  
  4         18  
  4         17  
  12         516  
  12         41  
  12         21  
  12         88  
  4         19  
  4         70  
  4         44  
  4         32  
  4         10  
  4         20  
  4         18  
  4         17  
  8         204  
  8         33  
  8         17  
  8         33  
  4         20  
  4         21  
144             package $class;
145             sub $method {
146             my \$self = shift;
147             my \$client = \$self->{'client'}; my \$object = \$self->{'object'};
148             my \@result = \$client->Call('CallMethod', \$object, '$method',
149             \@_);
150             return \@result if wantarray;
151             return \$result[0];
152             }
153             EOM
154 13         1349 goto &$AUTOLOAD;
155             }
156              
157             sub new {
158 4     4   27 my($class, $cl, $client, $object) = @_;
159 4 50       15 $class = ref($class) if ref($class);
160 4     4   25 no strict 'refs';
  4         8  
  4         746  
161 4         17 my $ocl = "${class}::$cl";
162 4 100       8 @{"${ocl}::ISA"} = $class unless @{"${ocl}::ISA"};
  3         78  
  4         52  
163 4         39 my $self = { 'client' => $client, 'object' => $object };
164              
165 4         16 bless($self, $ocl);
166 4         20 $self;
167             }
168              
169              
170             sub DESTROY {
171 4     4   94 my $saved_error = $@; # Save $@
172 4         10 my $self = shift;
173 4 50       24 if (my $client = delete $self->{'client'}) {
174 4         72 eval { $client->Call('DestroyHandle', $self->{'object'}) };
  4         14  
175             }
176 4         1500 $@ = $saved_error; # Restore $@
177             }
178              
179             1;
180              
181              
182             __END__