File Coverage

blib/lib/RPC/Simple/Factory.pm
Criterion Covered Total %
statement 123 145 84.8
branch 22 40 55.0
condition 8 27 29.6
subroutine 19 21 90.4
pod 8 9 88.8
total 180 242 74.3


line stmt bran cond sub pod time code
1             package RPC::Simple::Factory;
2              
3 1     1   4 use strict;
  1         1  
  1         25  
4 1     1   4 use warnings ;
  1         1  
  1         34  
5 1     1   4 use vars qw(@ISA @EXPORT $VERSION $serverPid);
  1         2  
  1         49  
6 1     1   822 use IO::Socket ;
  1         26634  
  1         6  
7 1     1   643 use Fcntl ;
  1         2  
  1         293  
8 1     1   6522 use Data::Dumper ;
  1         13990  
  1         90  
9 1     1   22 use Carp ;
  1         2  
  1         5655  
10              
11             require Exporter;
12              
13             ( $VERSION ) = '$Revision: 1.9 $ ' =~ /\$Revision:\s+([^\s]+)/;
14              
15             @ISA = qw(Exporter);
16             @EXPORT= qw(spawn) ;
17             # Items to export into callers namespace by default. Note: do not export
18             # names by default without a very good reason. Use EXPORT_OK instead.
19             # Do not simply export all your public functions/methods/constants.
20              
21             # Preloaded methods go here.
22              
23             # As a test may control several machines, several Factory object may be created
24              
25             # opens a connection to a remote host
26             # Tk top window, remote_host, port
27             sub new
28             {
29 1     1 1 1297 my $type = shift ;
30              
31 1         15 my ($tkTop,$verboseRef,$remote,$port,$timeout);
32              
33 1 50       14 if (ref $_[0])
34             {
35             # old style api
36 0         0 $tkTop = shift ;
37 0         0 $verboseRef = shift ;
38 0   0     0 $remote = shift || 'localhost';
39 0   0     0 $port = shift || 7810;
40 0   0     0 $timeout = shift || 0 ;
41             }
42             else
43             {
44             # new style
45 1         67 my %args = @_ ;
46              
47 1         11 $tkTop = $args{tk_top};
48 1         2 $verboseRef = $args{verbose_ref} ;
49 1   50     32 $remote = $args{remote_host} || 'localhost';
50 1   50     22 $port = $args{remote_port} || '7810' ;
51 1   50     19 $timeout = $args{timeout} || 0 ;
52             }
53              
54 1         200 my $self = {
55             verbose => $verboseRef,
56             handleIdx => 0,
57             remoteHostName => $remote
58             };
59              
60 1         25 my ($iaddr, $paddr, $proto, $line);
61              
62 1 50       22 if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
  0         0  
63              
64 1 50       4 print "No port" unless $port;
65              
66 1 50       6 my @time_arg = $timeout ? (Timeout => $timeout) : () ;
67 1         33 $self->{'socket'} = IO::Socket::INET -> new (PeerAddr => $remote,
68             PeerPort => $port,
69             Proto => 'tcp',
70             @time_arg) ;
71              
72 1 50       3391 die "Can't create a socket for $remote, port $port\n\t$!\n"
73             unless defined $self->{'socket'} ;
74              
75 1 50       20 fcntl($self->{'socket'},F_SETFL, O_NDELAY)
76             || die "fcntl failed $!\n";
77              
78 1         10 print "$type object created \n";
79              
80             # print "sleep over, closing\n";
81             # shutdown ($self->{'socket'}, 2) || print "close: $!";
82              
83 1         7 bless $self, $type ;
84              
85 1 50       5 if (defined $tkTop)
86             {
87             # register socket to TK's fileevent ...
88 0         0 $tkTop -> fileevent($self->{'socket'},
89             'readable' => [$self, 'readSock']) ;
90 0         0 $self->{tkTop} = $tkTop ;
91             }
92              
93 1         24 $self->{sockBuffer} = '' ;
94 1         7 return $self ;
95             }
96              
97             sub DESTROY
98             {
99 0     0   0 my $self = shift ;
100 0         0 print "closing Factory socket\n";
101              
102             # de-register from Tk
103 0 0       0 $self->{tkTop} -> fileevent($self->{'socket'},readable => '')
104             if defined $self->{tkTop} ;
105              
106             #$self->{socket}->close;
107 0 0 0     0 if(defined $self->{socket} && $self->{socket}->connected)
108             {
109 0         0 shutdown($self->{socket},2) ;
110             }
111             }
112              
113             sub logmsg
114             {
115 24     24 1 31 my $self = shift ;
116            
117 24 50 33     85 print @_ if (defined $self->{verbose} and ${$self->{verbose}} );
  24         109  
118             }
119              
120             sub newRemoteObject
121             {
122 1     1 1 3 my $self=shift ;
123 1         2 my $clientRef = shift ;
124 1         3 my $remoteClass = shift ; #optionnal
125            
126             # create an Agent tied to the client object
127 1         105 my $handle = RPC::Simple::Agent->new ($self,$clientRef,$self->{handleIdx},
128             $remoteClass,@_) ;
129            
130 1         5 $self->{handleTab}{$self->{handleIdx}++} = $handle ;
131 1         13 return $handle ;
132             }
133              
134             sub destroyRemoteObject
135             {
136 0     0 0 0 my $self=shift ;
137 0         0 my $idx = shift ;
138 0         0 $self->writeSockBuffer($idx, 'destroy' );
139 0         0 delete $self->{handleTab}{$idx} ;
140             }
141              
142             sub getRemoteHostName
143             {
144 1     1 1 2 my $self=shift ;
145 1         5 return $self->{remoteHostName} ;
146             }
147              
148             sub writeSockBuffer
149             {
150 2     2 1 3 my $self=shift ;
151 2         4 my $callingIdx = shift ; # index of Agent
152 2         2 my $method = shift ;
153 2         5 my $reqId = shift ;
154 2         2 my $param = shift ; # usually an array ref
155 2         3 my $objectName = shift ; # optionnal
156            
157 2         6 my $refs = [$param,$method,$reqId, $callingIdx ] ;
158 2         11 my $names = ['args','method','reqId','handle',] ;
159            
160 2 100       8 if (defined $objectName)
161             {
162 1         2 push @$refs, $objectName ;
163 1         25 push @$names, 'objectName' ;
164             }
165              
166 2         44 my $d = Data::Dumper->new ( $refs, $names ) ;
167 2         337 my $paramStr = "#begin\n".$d->Dumpxs."#end\n" ;
168             #my $str = sprintf("%6d",length($paramStr)) . $paramStr ;
169 2         4 my $str = $paramStr ;
170 2         9 $self->logmsg( "$str\n");
171              
172 2         7 $self->{sockBuffer} .= $str ;
173              
174 2         5 my $str2 = "#begin_buffer\n".$self->{sockBuffer}."#end_buffer\n" ;
175 1     1   15 no strict 'refs' ;
  1         3  
  1         196  
176 2         133 my $val = send($self->{'socket'} ,$str2,0) ;
177 2 50 33     22 if ( defined $val and $val == length($str2))
178             {
179 2         8 $self->logmsg( "$val bytes sent\n");
180             }
181             else
182             {
183 0         0 warn "write failed for \n",$str2 ;
184             }
185              
186 2         34 $self->{sockBuffer} = '' ;
187             }
188              
189             sub readSock
190             {
191 1     1 1 23 my $self = shift ;
192              
193 1         4 my $fh = $self->{'socket'} ;
194            
195 1         9 $self->logmsg( "readSock called\n");
196 1     1   7 no strict 'refs' ;
  1         2  
  1         203  
197            
198 1 50       104 if (eof $fh)
199             {
200             #print "closing connection\n";
201             #close $fh ;
202 0         0 return 0;
203             }
204            
205 1         2 my $line ;
206 1         5 my @codeTab = () ;
207 1         11 my $code = '' ;
208 1         3 my $codeEnd = 1 ;
209 1   66     83 while ( $line = $fh->getline or not $codeEnd )
210             {
211 17 50       550 next unless defined $line ;
212            
213 17         43 $self->logmsg( "->",$line );
214 17         30 $code .= $line ;
215            
216 17 100       46 if ($line =~ /\s*#end$/)
217             {
218 2         5 push @codeTab, $code ;
219 2         4 $code = '' ;
220 2         2 $codeEnd = 1 ;
221             }
222 17 100       398 if ($line =~ /\s*#begin$/
223             )
224             {
225 2         52 $codeEnd = 0 ;
226             }
227             }
228            
229 1     1   5 use strict ;
  1         1  
  1         457  
230            
231 1         64 foreach $code (@codeTab)
232             {
233             # these lexical variables are assigned in the eval
234 2         3 my ($args,$method,$reqId,$handle,$objectName) ;
235 2         201 eval $code ;
236            
237 2 50       14 if ($@)
    100          
238             {
239 0         0 print "failed eval ($@) of :\n",$code,"end evaled code\n" ;
240             }
241             elsif (defined $method)
242             {
243             # call object method directly
244 1         5 $self->logmsg( "calling method $method\n");
245 1         6 $self->{handleTab}{$handle} -> callMethod($method , $args) ;
246             }
247             else
248             {
249             # it's a call-back
250 1         12 $self->logmsg( "callback for handle $handle, request $reqId\n");
251 1         53 $self->{handleTab}{$handle}->treatCallBack($reqId, $args);
252             # or print "eval failed: $@\n";
253             }
254             }
255 1         130 return 1;
256             }
257              
258             # static method. spawn a server
259             sub spawn
260             {
261 1     1 1 39 my $port = shift ;
262 1         3 my $verbose = shift ;
263              
264 1         9290 $serverPid = fork ;
265              
266 1 50       111 if ($serverPid == 0)
267             {
268             # I am a server now
269 0         0 RPC::Simple::Server::mainLoop ($port,$verbose) ;
270 0         0 exit ; # well I should never go there
271             }
272 1         279 print "spawned server pid $serverPid\n" ; # don't use verbose
273 1         2000156 sleep 2 ; # let the server start
274 1         65 return $serverPid ;
275             }
276              
277             sub getSocket
278             {
279 2     2 1 23113 my $self = shift;
280 2         12 return $self->{socket};
281             }
282              
283             sub END
284             {
285 1 50 33 1   773 if (defined $serverPid and $serverPid != 0 )
286             {
287 1         131 print "killing process $serverPid\n";
288             # 15 is SIGTERM signal
289 1         66 kill (15, $serverPid) ;
290             }
291             }
292              
293             # Autoload methods go after =cut, and are processed by the autosplit program.
294              
295             1;
296             __END__