File Coverage

blib/lib/RMI/Node.pm
Criterion Covered Total %
statement 399 408 97.7
branch 140 204 68.6
condition 17 32 53.1
subroutine 117 117 100.0
pod 3 6 50.0
total 676 767 88.1


line stmt bran cond sub pod time code
1             package RMI::Node;
2              
3 38     38   112815 use strict;
  38         76  
  38         1430  
4 38     38   206 use warnings;
  38         76  
  38         4146  
5 38     38   20582 use version;
  38         58752  
  38         699  
6             our $VERSION = $RMI::VERSION;
7              
8             # Note: if any of these get proxied as full classes, we'd have issues.
9             # Since it's impossible to proxy a class which has already been "used",
10             # we use them at compile time...
11              
12 38     38   19761 use RMI;
  38         119  
  38         1207  
13 38     38   24521 use Tie::Array;
  38         32015  
  38         1295  
14 38     38   23233 use Tie::Hash;
  38         24107  
  38         1316  
15 38     38   29627 use Tie::Scalar;
  38         13972  
  38         1448  
16 38     38   23693 use Tie::Handle;
  38         75601  
  38         1160  
17 36     36   20048 use Data::Dumper;
  36         143118  
  36         2275  
18 36     36   9922 use Scalar::Util;
  36         92  
  36         1566  
19 34     34   328 use Carp;
  34         69  
  34         24031  
20             require 'Config_heavy.pl';
21              
22              
23             # public API
24              
25             _mk_ro_accessors(qw/reader writer/);
26              
27             sub new {
28 33     33 1 616 my $class = shift;
29 33         1855 my $self = bless {
30             reader => undef,
31             writer => undef,
32             _sent_objects => {},
33             _received_objects => {},
34             _received_and_destroyed_ids => [],
35             _tied_objects_for_tied_refs => {},
36             @_
37             }, $class;
38 33 50       1616 if (my $p = delete $self->{allow_packages}) {
39 9         63 $self->{allow_packages} = { map { $_ => 1 } @$p };
  9         91  
40             }
41 33         1197 for my $p (@RMI::Node::properties) {
42 152 50       1217 unless (exists $self->{$p}) {
43 8         17 die "no $p on object!"
44             }
45             }
46 33         661 return $self;
47             }
48              
49             sub close {
50 21     16 1 3803 my $self = $_[0];
51 15 50       162 $self->{writer}->close unless $self->{reader} == $self->{writer};
52 16         14803 $self->{reader}->close;
53             }
54              
55             sub send_request_and_receive_response {
56 249     249 0 514 my $self = shift;
57              
58 249 50       694 if ($RMI::DEBUG) {
59 8         322 print "$RMI::DEBUG_MSG_PREFIX N: $$ calling via $self: @_\n";
60             }
61            
62 249         501 my $wantarray = wantarray;
63              
64             # Specs to get control of the serialization process are optional,
65             # and may be at the beginning of the parameter list.
66             # The remainder of the params are only analyzed on the caller's side.
67 249 50       715 my $opts = shift(@_) if ref($_[0]) eq 'HASH';
68              
69 249 50       3051 $self->_send('query',[$wantarray, @_],$opts) or die "failed to send! $!";
70            
71 249         99694 for (1) {
72 257         1956 my ($message_type, $message_data) = $self->_receive();
73 257 100       1079 if ($message_type eq 'result') {
    100          
    100          
    50          
74 246 100       934 if ($wantarray) {
75 58 50       144 print "$RMI::DEBUG_MSG_PREFIX N: $$ returning list @$message_data\n" if $RMI::DEBUG;
76 58         887 return @$message_data;
77             }
78             else {
79 196 50       488 print "$RMI::DEBUG_MSG_PREFIX N: $$ returning scalar $message_data->[0]\n" if $RMI::DEBUG;
80 196         2383 return $message_data->[0];
81             }
82             }
83             elsif ($message_type eq 'close') {
84 9         291 return;
85             }
86             elsif ($message_type eq 'query') {
87 16         141 $self->_process_query($message_data);
88 16         40 redo;
89             }
90             elsif ($message_type eq 'exception') {
91 10         378 die $message_data->[0];
92             }
93             else {
94 8         73 die "unexpected message type from RMI message: $message_type";
95             }
96             }
97             }
98              
99             sub receive_request_and_send_response {
100 245     245 1 405 my ($self) = @_;
101 245         1828 my ($message_type, $message_data) = $self->_receive();
102 245 100       756 if ($message_type eq 'query') {
    50          
103 241         1542 my ($response_type, $response_data) = $self->_process_query($message_data);
104 240         1579 return ($message_type, $message_data, $response_type, $response_data);
105             }
106             elsif ($message_type eq 'close') {
107 22         128 return;
108             }
109             else {
110 12         65 die "Unexpected message type $message_type! message_data was:" . Dumper::Dumper($message_data);
111             }
112             }
113              
114             # private API
115              
116             _mk_ro_accessors(qw/_sent_objects _received_objects _received_and_destroyed_ids _tied_objects_for_tied_refs/);
117              
118             sub _send {
119 488     489   1395 my ($self, $message_type, $message_data, $opts) = @_;
120 485         2919 my $s = $self->_serialize($message_type,$message_data, $opts);
121            
122 484 50       1480 print "$RMI::DEBUG_MSG_PREFIX N: $$ sending: $s\n" if $RMI::DEBUG;
123 488         3405 return $self->{writer}->print($s,"\n");
124             }
125              
126             sub _receive {
127 498     498   922 my ($self) = @_;
128 498 50       1250 print "$RMI::DEBUG_MSG_PREFIX N: $$ receiving\n" if $RMI::DEBUG;
129              
130 498         20818 my $serialized_blob = $self->{reader}->getline;
131 499 100       3542683 if (not defined $serialized_blob) {
132             # a failure to get data returns a message type of 'close', and undefined message_data
133 23 50       117 print "$RMI::DEBUG_MSG_PREFIX N: $$ connection closed\n" if $RMI::DEBUG;
134 23         1028 $self->{is_closed} = 1;
135 23         7942 return ('close',undef);
136             }
137 485 50       1587 print "$RMI::DEBUG_MSG_PREFIX N: $$ got $serialized_blob" if $RMI::DEBUG;
138 485 50 33     1848 print "\n" if $RMI::DEBUG and not defined $serialized_blob;
139            
140 485         4135 my ($message_type,$message_data) = $self->_deserialize($serialized_blob);
141 488         1503 return ($message_type, $message_data);
142             }
143              
144             sub _process_query {
145 248     249   894 my ($self, $message_data) = @_;
146              
147 248         571 my $wantarray = shift @$message_data;
148 248         472 my $call_type = shift @$message_data;
149            
150 248         823 do {
151 34     34   244 no warnings;
  34         98  
  34         10581  
152 248 50       657 print "$RMI::DEBUG_MSG_PREFIX N: $$ processing query $call_type in wantarray context $wantarray with : @$message_data\n" if $RMI::DEBUG;
153             };
154            
155            
156             # swap call_ for _respond_to_
157 248         748 my $method = '_respond_to_' . substr($call_type,5);
158            
159 248         625 my @result;
160              
161 246         653 push @RMI::executing_nodes, $self;
162 246         354 eval {
163 246 100       1158 if (not defined $wantarray) {
    100          
164 23 50       106 print "$RMI::DEBUG_MSG_PREFIX N: $$ object call with undef wantarray\n" if $RMI::DEBUG;
165 23         125 $self->$method(@$message_data);
166             }
167             elsif ($wantarray) {
168 60 50       390 print "$RMI::DEBUG_MSG_PREFIX N: $$ object call with true wantarray\n" if $RMI::DEBUG;
169 56         427 @result = $self->$method(@$message_data);
170             }
171             else {
172 179 50       450 print "$RMI::DEBUG_MSG_PREFIX N: $$ object call with false wantarray\n" if $RMI::DEBUG;
173 179         1451 my $result = $self->$method(@$message_data);
174 179         2292 @result = ($result);
175             }
176             };
177 245         1201 pop @RMI::executing_nodes;
178              
179             # we MUST undef these in case they are the only references to remote objects which need to be destroyed
180             # the DESTROY handler will queue them for deletion, and _send() will include them in the message to the other side
181 245         1001 @$message_data = ();
182            
183 245         400 my ($return_type, $return_data);
184 245 100       500 if ($@) {
185 12 50       280 print "$RMI::DEBUG_MSG_PREFIX N: $$ executed with EXCEPTION (unserialized): $@\n" if $RMI::DEBUG;
186 12         59 ($return_type, $return_data) = ('exception',[$@]);
187             }
188             else {
189 243 50       592 print "$RMI::DEBUG_MSG_PREFIX N: $$ executed with result (unserialized): @result\n" if $RMI::DEBUG;
190 239         908 ($return_type, $return_data) = ('result',\@result);
191             }
192            
193 241         1534 $self->_send($return_type, $return_data);
194 245         8346 return ($return_type, $return_data);
195             }
196              
197             # private API for the server-ish role
198              
199             sub _respond_to_function {
200 81     83   434 my ($self, $fname, @params) = @_;
201 34     34   218 no strict 'refs';
  34         68  
  34         3843  
202 81         992 $fname->(@params);
203             }
204              
205             sub _respond_to_class_method {
206 23     25   208 my ($self, $class, $method, @params) = @_;
207 23         541 $class->$method(@params);
208             }
209              
210             sub _respond_to_object_method {
211 54     52   235 my ($self, $object, $method, @params) = @_;
212 50         445 $object->$method(@params);
213             }
214              
215             sub _respond_to_use {
216 13     15   260 my ($self,$class,$module,$has_args,@use_args) = @_;
217              
218 34     34   177 no strict 'refs';
  34         63  
  34         37882  
219 13 100 66     133 if ($class and not $module) {
    50 33        
220 11         26 $module = $class;
221 11         305 $module =~ s/::/\//g;
222 11         56 $module .= '.pm';
223             }
224             elsif ($module and not $class) {
225 8         17 $class = $module;
226 8         247 $class =~ s/\//::/g;
227 8         43 $class =~ s/.pm$//;
228             }
229            
230 13         52 my $n = $RMI::Exported::count++;
231 13         239 my $tmp_package_to_catch_exports = 'RMI::Exported::P' . $n;
232 13         103 my $src = "
233             package $tmp_package_to_catch_exports;
234             require $class;
235             my \@exports = ();
236             if (\$has_args) {
237             if (\@use_args) {
238             $class->import(\@use_args);
239             \@exports = grep { ${tmp_package_to_catch_exports}->can(\$_) } keys \%${tmp_package_to_catch_exports}::;
240             }
241             else {
242             # print qq/no import because of empty list!/;
243             }
244             }
245             else {
246             $class->import();
247             \@exports = grep { ${tmp_package_to_catch_exports}->can(\$_) } keys \%${tmp_package_to_catch_exports}::;
248             }
249             return (\$INC{'$module'}, \@exports);
250             ";
251 13         2336 my ($path, @exported) = eval($src);
252 13 50       446 die $@ if $@;
253 13         99 return ($class,$module,$path,@exported);
254             }
255              
256             sub _respond_to_use_lib {
257 6     8   14 my $self = shift;
258 6         244 my $lib = shift;
259 6         39 require lib;
260 6         14 return lib->import($lib);
261             }
262              
263             sub _respond_to_eval {
264 100     102   414 my $self = shift;
265 100         194 my $src = shift;
266 100 100       274 if (wantarray) {
267 41         2716 my @result = eval $src;
268 41 50       181 die $@ if $@;
269 41         143 return @result;
270             }
271             else {
272 65         4216 my $result = eval $src;
273 64 100       415 die $@ if $@;
274 63         235 return $result;
275             }
276             }
277              
278             sub _respond_to_coderef {
279             # This is used when a CODE ref is proxied, since you can't tie CODE refs.
280             # It does not have a matching caller in RMI::Client.
281             # The other reference types are handled by "tie" to RMI::ProxyReferecnce.
282              
283             # NOTE: It's important to shift these two parameters off since goto must
284             # pass the remainder of @_ to the subroutine.
285 13     15   263 my $self = shift;
286 13         58 my $sub_id = shift;
287 13         33 my $sub = $self->{_sent_objects}{$sub_id};
288 13 50 33     319 die "$sub is not a CODE ref. came from $sub_id\n" unless $sub and ref($sub) eq 'CODE';
289 13         162 goto $sub;
290             }
291              
292             # The private API for the client-ish role of the RMI::Node is still in the RMI::Client module,
293             # where it is documented. All of that API is a thin wrapper for methods here.
294              
295             # serialize params when sending a query, or results when sending a response
296              
297             sub _serialize {
298 482     484   949 my ($self, $message_type, $message_data, $opts) = @_;
299            
300             # TODO: we previously had no knowledge in the client of the type of call being made,
301             # but to support overrides we now need it. Refactor this conditional logic!!
302 482 100       1499 if ($message_type eq 'query') {
303 247         486 my $call_type = $message_data->[1];
304 251         466 my $pkg;
305             my $sub;
306 251 100 100     1800 if ($call_type eq 'call_object_method') {
    100 66        
    100 33        
    50          
307 50         142 $pkg = ref($message_data->[2]);
308 50         248 $pkg =~ s/RMI::Proxy:://;
309 50         354 $sub = $message_data->[3];
310             }
311             elsif ($call_type eq 'call_class_method') {
312 19         72 $pkg = $message_data->[2];
313 19         49 $sub = $message_data->[3];
314             }
315             elsif ($call_type eq 'call_function') {
316 81         824 ($pkg,$sub) = ($message_data->[2] =~ /^(.*)::([^\:]*)$/);
317             }
318             elsif (
319             $call_type eq 'call_eval'
320             or $call_type eq 'call_coderef'
321             or $call_type eq 'call_use'
322             or $call_type eq 'call_use_lib'
323             ) {
324 115         272 $pkg = '-' . $call_type;
325 115 100       292 if ($call_type eq 'call_use') {
326 13         235 $sub = $message_data->[2];
327 13 100       70 if (!$sub) {
328 8         38 $sub = $message_data->[3];
329 8         469 $sub =~ s/.pm$//;
330 8         53 $sub =~ s/\//\::/g;
331             }
332 13         29 $sub .= '';
333             }
334             else {
335 108         528 $sub = $message_data->[2] . '';
336             }
337             }
338             else {
339 6         48 die "no handling for CALL TYPE $call_type?";
340             }
341              
342 247 50       643 unless ($pkg) {
343 6         253 die "Failed to resolve a pkg/sub pair for query @$message_data!";
344             }
345              
346 247         1000 my $default_opts = $RMI::ProxyObject::DEFAULT_OPTS{$pkg}{$sub};
347 247 50       595 print "$RMI::DEBUG_MSG_PREFIX N: $$ $message_type $call_type on $pkg $sub has default opts " . Data::Dumper::Dumper($default_opts) . "\n" if $RMI::DEBUG;
348 247 100       914 if ($default_opts) {
349 7 50       43 if ($opts) {
350 6         13 $opts = { %$default_opts, %$opts };
351 6 0       243 print "$RMI::DEBUG_MSG_PREFIX N: $$ $message_type $call_type on $pkg $sub merged with specified opts for combined set: " . Data::Dumper::Dumper($opts) . "\n" if $RMI::DEBUG;
352             }
353             else {
354 7         31 $opts = $default_opts;
355             }
356             }
357              
358             }
359              
360 482         1849 my $sent_objects = $self->{_sent_objects};
361              
362             # there is currently only one option to serialize: a global "copy" flag.
363 482         818 my $copy;
364 482 100       1083 if ($opts) {
365 11         32 $copy = delete $opts->{copy};
366 11 50       311 if (%$opts) {
367 10         46 Carp::confess("Uknown options! The only supported option is the 'copy' flag.");
368             }
369             }
370              
371 482         581 my @serialized;
372 482 50       1652 Carp::confess("expected message_type, message_data_arrayref, optional_opts_hashref as params") unless ref($message_data);
373 482         1133 for my $o (@$message_data) {
374 1387 100       2937 if (my $type = ref($o)) {
375             # sending some sort of reference
376 202 100       1309 if (my $key = $RMI::Node::remote_id_for_object{$o}) {
    100          
377             # this is a proxy object on THIS side: the real object will be used on the remote side
378 124 50       332 print "$RMI::DEBUG_MSG_PREFIX N: $$ proxy $o references remote $key:\n" if $RMI::DEBUG;
379 124         246 push @serialized, 3, $key;
380 124         767 next;
381             }
382             elsif($copy) {
383             # a reference on this side which should be copied on the other side instead of proxied
384             # this never happens by default in the RMI modules, only when specially requested for performance
385             # or to get around known bugs in the C<->Perl interaction in some modules (DBI).
386 9         62 push @serialized, 4, $o;
387             }
388             else {
389             # a reference originating on this side: send info so the remote side can create a proxy
390              
391             # TODO: use something better than stringification since this can be overridden!!!
392 85         248 my $key = "$o";
393            
394             # TODO: handle extracting the base type for tying for regular objects which does not involve parsing
395 85         512 my $base_type = substr($key,index($key,'=')+1);
396 81         371 $base_type = substr($base_type,0,index($base_type,'('));
397 81         138 my $code;
398 81 100       391 if ($base_type ne $type) {
399             # blessed reference
400 22         9188 $code = 1;
401 22 50       99 if (my $allowed = $self->{allow_packages}) {
402 4 0       370 unless ($allowed->{ref($o)}) {
403 4         27 die "objects of type " . ref($o) . " cannot be passed from this RMI node!";
404             }
405             }
406             }
407             else {
408             # regular reference
409 63         246 $code = 2;
410             }
411            
412 81         469 push @serialized, $code, $key;
413 81         420 $sent_objects->{$key} = $o;
414             }
415             }
416             else {
417             # sending a non-reference value
418 1189         2645 push @serialized, 0, $o;
419             }
420             }
421 480 50       1408 print "$RMI::DEBUG_MSG_PREFIX N: $$ $message_type translated for serialization to @serialized\n" if $RMI::DEBUG;
422              
423 480         983 @$message_data = (); # essential to get the DESTROY handler to fire for proxies we're not holding on-to
424              
425             # Do this after emptying the $message_data array, so the list will be expanded to include objects which
426             # were sent from the other side, and are only referenced in the data we're returning.
427 480         1014 my $received_and_destroyed_ids = $self->{_received_and_destroyed_ids};
428 484 50       1394 print "$RMI::DEBUG_MSG_PREFIX N: $$ destroyed proxies: @$received_and_destroyed_ids\n" if $RMI::DEBUG;
429 484         1368 unshift @serialized, [@$received_and_destroyed_ids];
430 484         873 @$received_and_destroyed_ids = ();
431              
432             # TODO: the use of Data::Dumper here is pure laziness. The @serialized list contains no references,
433             # and could be turned into a string with something simpler than data dumper. It could also be parsed with
434             # something simpler than eval() on the other side. The only thing to be careful of is that parsing
435             # currently expects the records are divided by newlines (instead of sending a message length or other
436             # terminator) and Dumper conveniently escapes newlines in any strings we pass.
437 484         4628 my $serialized_blob = Data::Dumper->new([[$message_type, @serialized]])->Terse(1)->Indent(0)->Useqq(1)->Dump;
438 484 50       58222 print "$RMI::DEBUG_MSG_PREFIX N: $$ $message_type serialized as $serialized_blob\n" if $RMI::DEBUG;
439 484 50       2826 if ($serialized_blob =~ s/\n/ /gms) {
440 8         252 die "newline found in message data!";
441             }
442            
443 484         2935 return $serialized_blob;
444             }
445              
446             # deserialize params when receiving a query, or results when receiving a response
447              
448             sub _deserialize {
449 484     488   985 my ($self, $serialized_blob) = @_;
450            
451             # see TODO above for switching from Dumper/eval to something simpler.
452 33     33   895 my $serialized = eval "no strict; no warnings; $serialized_blob";
  33     31   3214  
  33     30   2833  
  31     29   226  
  31     28   97  
  31     28   3972  
  30     26   1104  
  29     26   64  
  29     7   1767  
  29     6   4137  
  23     6   51  
  23     6   1342  
  28     6   218  
  28     6   90  
  28     6   1221  
  28     6   174  
  28     6   207  
  28     6   1241  
  26     6   183  
  26     6   59  
  26     6   4324  
  26     6   177  
  26     6   56  
  26     6   1109  
  480     6   52965  
  1     6   9747  
  5     6   2824  
  5     6   123  
        6      
        6      
        6      
        6      
        6      
        6      
        6      
        6      
        6      
        6      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        4      
        3      
        3      
        2      
        2      
        2      
        2      
453              
454 484 50       3485 if ($@) {
455 8         19 die "Exception de-serializing message: $@";
456             }
457              
458 484         2016 my $message_type = shift @$serialized;
459 484 50       1330 if (! defined $message_type) {
460 4         10 die "unexpected undef type from incoming message:" . Data::Dumper::Dumper($serialized);
461             }
462              
463 484         814 do {
464 34     34   247 no warnings;
  34         100  
  34         15224  
465 484 50       4604 print "$RMI::DEBUG_MSG_PREFIX N: $$ processing (serialized): @$serialized\n" if $RMI::DEBUG;
466             };
467            
468 480         1711 my @message_data;
469              
470 484         1354 my $sent_objects = $self->{_sent_objects};
471 484         878 my $received_objects = $self->{_received_objects};
472 484         894 my $received_and_destroyed_ids = shift @$serialized;
473            
474 484         1428 while (@$serialized) {
475 1371         1774 my $type = shift @$serialized;
476 1371         2283 my $value = shift @$serialized;
477 1371 100 100     4141 if ($type == 0) {
    100          
    100          
    50          
478             # primitive value
479 1191 0       2391 print "$RMI::DEBUG_MSG_PREFIX N: $$ - primitive " . (defined($value) ? $value : "") . "\n" if $RMI::DEBUG;
    50          
480 1191         3387 push @message_data, $value;
481             }
482             elsif ($type == 1 or $type == 2) {
483             # exists on the other side: make a proxy
484 93         10856 my $o = $received_objects->{$value};
485 89 100       303 unless ($o) {
486 86         830 my ($remote_class,$remote_shape) = ($value =~ /^(.*?=|)(.*?)\(/);
487 78         385 chop $remote_class;
488 78         160 my $t;
489 78 100 66     594 if ($remote_shape eq 'ARRAY') {
    100          
    100          
    100          
    50          
490 14         231 $o = [];
491 14         126 $t = tie @$o, 'RMI::ProxyReference', $self, $value, "$o", 'Tie::StdArray';
492             }
493             elsif ($remote_shape eq 'HASH') {
494 22         66 $o = {};
495 18         626 $t = tie %$o, 'RMI::ProxyReference', $self, $value, "$o", 'Tie::StdHash';
496             }
497             elsif ($remote_shape eq 'SCALAR') {
498 6         34 my $anonymous_scalar;
499 10         23 $o = \$anonymous_scalar;
500 10         270 $t = tie $$o, 'RMI::ProxyReference', $self, $value, "$o", 'Tie::StdScalar';
501             }
502             elsif ($remote_shape eq 'CODE') {
503 46         119 my $sub_id = $value;
504             $o = sub {
505 11     19   1943 $self->send_request_and_receive_response('call_coderef', $sub_id, @_);
506 46         459 };
507             # TODO: ensure this cleans up on the other side when it is destroyed
508             }
509             elsif ($remote_shape eq 'GLOB' or $remote_shape eq 'IO') {
510 10         38 $o = \do { local *HANDLE };
  10         59  
511 10         245 $t = tie *$o, 'RMI::ProxyReference', $self, $value, "$o", 'Tie::StdHandle';
512             }
513             else {
514 4         24 die "unknown reference type for $remote_shape for $value!!";
515             }
516 74 100       247 if ($type == 1) {
517 20 100       265 if ($RMI::proxied_classes{$remote_class}) {
518 7         47 bless $o, $remote_class;
519             }
520             else {
521             # Put the object into a custom subclass of RMI::ProxyObject
522             # this allows class-wide customization of how proxying should
523             # occur. It also makes Data::Dumper results more readable.
524 21         74 my $target_class = 'RMI::Proxy::' . $remote_class;
525 19 100       218 unless ($RMI::classes_with_proxied_objects{$remote_class}) {
526 34     34   226 no strict 'refs';
  34         119  
  34         1398  
527 11         38 @{$target_class . '::ISA'} = ('RMI::ProxyObject');
  13         611  
528 34     34   743 no strict;
  33         248  
  33         1341  
529 34     34   172 no warnings;
  34         64  
  34         21489  
530 13         258 local $SIG{__DIE__} = undef;
531 12         107 local $SIG{__WARN__} = undef;
532 12     6   739 eval "use $target_class";
533 12         237 $RMI::classes_with_proxied_objects{$remote_class} = 1;
534             }
535 18         97 bless $o, $target_class;
536             }
537             }
538 75         345 $received_objects->{$value} = $o;
539 75         782 Scalar::Util::weaken($received_objects->{$value});
540 76         277 my $o_id = "$o";
541 78 100       325 my $t_id = "$t" if defined $t;
542 78         528 $RMI::Node::node_for_object{$o_id} = $self;
543 78         277 $RMI::Node::remote_id_for_object{$o_id} = $value;
544 78 100       395 if ($t) {
545             # ensure calls to work with the "tie-buddy" to the reference
546             # result in using the orinigla reference on the "real" side
547 36         536 $RMI::Node::node_for_object{$t_id} = $self;
548 35         158 $RMI::Node::remote_id_for_object{$t_id} = $value;
549             }
550             }
551            
552 80         165 push @message_data, $o;
553 80 50       461 print "$RMI::DEBUG_MSG_PREFIX N: $$ - made proxy for $value\n" if $RMI::DEBUG;
554             }
555             elsif ($type == 3) {
556             # exists on this side, and was a proxy on the other side: get the real reference by id
557 125         290 my $o = $sent_objects->{$value};
558 125 50 0     333 print "$RMI::DEBUG_MSG_PREFIX N: $$ reconstituting local object $value, but not found in my sent objects!\n" and die unless $o;
559 125         338 push @message_data, $o;
560 120 50       1848 print "$RMI::DEBUG_MSG_PREFIX N: $$ - resolved local object for $value\n" if $RMI::DEBUG;
561             }
562             elsif ($type == 4) {
563             # fully serialized blob
564             # this is never done by default, but is part of shortcut/optimization on a per-class basis
565 3         8 push @message_data, $value;
566             }
567             }
568 478 50       1398 print "$RMI::DEBUG_MSG_PREFIX N: $$ remote side destroyed: @$received_and_destroyed_ids\n" if $RMI::DEBUG;
569 478         1207 my @done = grep { defined $_ } delete @$sent_objects{@$received_and_destroyed_ids};
  15         67  
570 482 50       1789 unless (@done == @$received_and_destroyed_ids) {
571 6         44 print "Some IDS not found in the sent list: done: @done, expected: @$received_and_destroyed_ids\n";
572             }
573              
574 478         2380 return ($message_type,\@message_data);
575             }
576              
577             # this proxies a single variable
578              
579             sub bind_local_var_to_remote {
580 48     50 0 2027 my $self = shift;
581 44         107 my $local_var = shift;
582 48 100       168 my $remote_var = (@_ ? shift : $local_var);
583            
584 44         187 my $type = substr($local_var,0,1);
585 42 50       133 if (index($local_var,'::')) {
586 42         88 $local_var = substr($local_var,1);
587             }
588             else {
589 0         0 my $caller = caller();
590 0         0 $local_var = $caller . '::' . substr($local_var,1);
591             }
592              
593 42 50       141 unless ($type eq substr($remote_var,0,1)) {
594 0         0 die "type mismatch: local var $local_var has type $type, while remote is $remote_var!";
595             }
596 42 50       97 if (index($remote_var,'::')) {
597 42         95 $remote_var = substr($remote_var,1);
598             }
599             else {
600 0         0 my $caller = caller();
601 0         0 $remote_var = $caller . '::' . substr($remote_var,1);
602             }
603            
604 42         106 my $src = '\\' . $type . $remote_var . ";\n";
605 42         267 my $r = $self->call_eval($src);
606 42 50       149 die $@ if $@;
607 42         122 $src = '*' . $local_var . ' = $r' . ";\n";
608 42         12402 eval $src;
609 42 50       199 die $@ if $@;
610 42         182 return 1;
611             }
612              
613             # this proxies an entire class instead of just a single object
614              
615             sub bind_local_class_to_remote {
616 7     15 0 17 my $self = shift;
617 7         101 my ($class,$module,$path,@exported) = $self->call_use(@_);
618 7         20 my $re_bind = 0;
619 7 100       113 if (my $prior = $RMI::proxied_classes{$class}) {
    100          
620 1 50       39 if ($prior != $self) {
621 0         0 die "class $class has already been proxied by another RMI client: $prior!";
622             }
623             else {
624             # re-binding a class to the same remote side doesn't hurt,
625             # and allowing it allows the effect of export to occur
626             # in multiple places on the client side.
627             }
628             }
629             elsif (my $path = $INC{$module}) {
630 1         26 die "module $module has already been used locally from path: $path";
631             }
632 34     34   225 no strict 'refs';
  34         68  
  34         10106  
633 6         37 for my $sub (qw/AUTOLOAD DESTROY can isa/) {
634 24         32 *{$class . '::' . $sub} = \&{ 'RMI::ProxyObject::' . $sub }
  24         206  
  24         324  
635             }
636 6 100       30 if (@exported) {
637 3   33     44 my $caller ||= caller(0);
638 3 50       16 if (substr($caller,0,5) eq 'RMI::') { $caller = caller(1) }
  3         8  
639 3         7 for my $sub (@exported) {
640 36         168 my @pair = ('&' . $caller . '::' . $sub => '&' . $class . '::' . $sub);
641 36 50       87 print "$RMI::DEBUG_MSG_PREFIX N: $$ bind pair $pair[0] $pair[1]\n" if $RMI::DEBUG;
642 36         233 $self->bind_local_var_to_remote(@pair);
643             }
644             }
645 6         19 $RMI::proxied_classes{$class} = $self;
646 6         27 $INC{$module} = $self;
647 6 50       41 print "$class used remotely via $self. Module $module found at $path remotely.\n" if $RMI::DEBUG;
648             }
649              
650             # used for testing
651              
652             sub _remote_has_ref {
653 3     11   7 my ($self,$obj) = @_;
654 3         9 my $id = "$obj";
655 3         22 my $has_sent = $self->send_request_and_receive_response('call_eval', 'exists $RMI::executing_nodes[-1]->{_received_objects}{"' . $id . '"}');
656             }
657              
658             sub _remote_has_sent {
659 0     6   0 my ($self,$obj) = @_;
660 0         0 my $id = "$obj";
661 0         0 my $has_sent = $self->send_request_and_receive_response('call_eval', 'exists $RMI::executing_nodes[-1]->{_sent_objects}{"' . $id . '"}');
662             }
663              
664             # this generate basic accessors w/o using any other Perl modules which might have proxy effects
665              
666             sub _mk_ro_accessors {
667 34     34   194 no strict 'refs';
  34         63  
  34         4190  
668 94     100   267 my $class = caller();
669 94         257 for my $p (@_) {
670 258         411 my $pname = $p;
671 262 50   155   989 *{$class . '::' . $pname} = sub { die "$pname is read-only!" if @_ > 1; $_[0]->{$pname} };
  262         1970  
  155         7796  
  155         1094  
672             }
673 34     34   217 no warnings;
  34         74  
  34         3824  
674 104         282 push @{ $class . '::properties'}, @_;
  94         706  
675             }
676              
677             =pod
678              
679             =head1 NAME
680              
681             RMI::Node - base class for RMI::Client and RMI::Server
682              
683             =head1 VERSION
684              
685             This document describes RMI::Node v0.10.
686              
687             =head1 SYNOPSIS
688            
689             # applications should use B and B
690             # this example is for new client/server implementors
691            
692             pipe($client_reader, $server_writer);
693             pipe($server_reader, $client_writer);
694             $server_writer->autoflush(1);
695             $client_writer->autoflush(1);
696            
697             $c = RMI::Node->new(
698             reader => $client_reader,
699             writer => $client_writer,
700             );
701            
702             $s = RMI::Node->new(
703             writer => $server_reader,
704             reader => $server_writer,
705             );
706            
707             sub main::add { return $_[0] + $_[1] }
708            
709             if (fork()) {
710             # service one request and exit
711             require IO::File;
712             $s->receive_request_and_send_response();
713             exit;
714             }
715            
716             # send one request and get the result
717             $sum = $c->send_request_and_receive_response('call_function', 'main::add', 5, 6);
718            
719             # we might have also done..
720             $robj = $c->send_request_and_receive_response('call_class_method', 'IO::File', 'new', '/my/file');
721            
722             # this only works on objects which are remote proxies:
723             $txt = $c->send_request_and_receive_response('call_object_method', $robj, 'getline');
724            
725             =head1 DESCRIPTION
726              
727             This is the base class for RMI::Client and RMI::Server. RMI::Client and RMI::Server
728             both implement a wrapper around the RMI::Node interface, with convenience methods
729             around initiating the sending or receiving of messages.
730              
731             An RMI::Node object embeds the core methods for bi-directional communication.
732             Because the server often has to make counter requests of the client, the pair
733             will often switch functional roles several times in the process of servicing a
734             particular call. This class is not technically abstract, as it is fully functional in
735             either the client or server role without subclassing. Most direct coding against
736             this API, however, should be done by implementors of new types of clients/servers.
737              
738             See B and B for the API against which application code
739             should be written. See B for an overview of how clients and servers interact.
740             The documentation in this module will describe the general piping system between
741             clients and servers.
742              
743             An RMI::Node requires that the reader/writer handles be explicitly specified at
744             construction time. It also requires and that the code which uses it is be wise
745             about calling methods to send and recieve data which do not cause it to block
746             indefinitely. :)
747              
748             =head1 METHODS
749              
750             =head2 new()
751            
752             $n = RMI::Node->new(reader => $fh1, writer => $fh2);
753              
754             The constructor for RMI::Node objects requires that a reader and writer handle be provided. They
755             can be the same handle if the handle is bi-directional (as with TCP sockets, see L).
756              
757             =head2 close()
758              
759             $n->close();
760              
761             Closes handles, and does any additional required bookeeping.
762            
763             =head2 send_request_and_recieve_response()
764              
765             @result = $n->send_request_and_recieve_response($call_type,@data);
766              
767             @result = $n->send_request_and_recieve_response($opts_hashref, $call_type, @data);
768              
769             This is the method behind all of the call_* methods on RMI::Client objects.
770             It is also the method behind the proxied objects themselves (in AUTOLOAD).
771              
772             The optional initial hashref allows special serialization control. It is currently
773             only used to force serializing instead of proxying in some cases where this is
774             helpful and safe.
775              
776             The call_type maps to the client request, and is one of:
777             call_function
778             call_class_method
779             call_object_method
780             call_eval
781             call_use
782             call_use_lib
783              
784             The interpretation of the @data parameters is dependent on the particular call_type, and
785             is handled entirely on the remote side.
786              
787             =head2 receive_request_and_send_response()
788              
789             This method waits for a single request to be received from its reader handle, services
790             the request, and sends the results through the writer handle.
791            
792             It is possible that, while servicing the request, it will make counter requests, and those
793             counter requests, may yield counter-counter-requests which call this method recursively.
794              
795             =head2 virtual_lib()
796              
797             This method returns an anonymous subroutine which can be used in a "use lib $mysub"
798             call, to cause subsequent "use" statements to go through this node to its partner.
799            
800             e.x.:
801             use lib RMI::Client::Tcp->new(host=>'myserver',port=>1234)->virtual_lib;
802            
803             If a client is constructed for other purposes in the application, the above
804             can also be accomplished with: $client->use_lib_remote(). (See L)
805              
806             =head1 INTERNALS: MESSAGE TYPES
807              
808             The RMI internals are built around sending a "message", which has a type, and an
809             array of data. The interpretation of the message data array is based on the message
810             type.
811              
812             The following message types are passed within the current implementation:
813              
814             =head2 query
815              
816             A request that logic execute on the remote side on behalf of the sender.
817             This includes object method calls, class method calls, function calls,
818             remote calls to eval(), and requests that the remote side load modules,
819             add library paths, etc.
820            
821             This is the type for standard remote method invocatons.
822            
823             The message data contains, in order:
824              
825             - wantarray 1, '', or undef, depending on the requestor's calling context.
826             This is passed to the remote side, and also used on the
827             local side to control how results are returned.
828              
829             - object/class A class name, or an object which is a proxy for something on the remote side.
830             This value is not present for plain function calls, or evals.
831              
832             - method_name This is the name of the method to call.
833             This is a fully-qualified function name for plain function calls.
834              
835             - param1 The first parameter to the function/method call.
836             Note that parameters are "passed" to eval as well by exposing @_.
837              
838             - ... The next parameter to the function/method call, etc.
839              
840              
841             =head2 result
842              
843             The return value from a succesful "query" which does not result in an
844             exception being thrown on the remote side.
845            
846             The message data contains the return value or values of that query.
847            
848             =head2 exception
849              
850             The response to a query which resulted in an exception on the remote side.
851            
852             The message data contains the value thrown via die() on the remote side.
853            
854             =head2 close
855              
856             Indicatees that the remote side has closed the connection. This is actually
857             constructed on the receiver end when it fails to read from the input stream.
858            
859             The message data is undefined in this case.
860              
861             =head1 INTERNALS: WIRE PROTOCOL
862              
863             The _send() and _receive() methods are symmetrical. These two methods are used
864             by the public API to encapsulate message transmission and reception. The _send()
865             method takes a message_type and a message_data arrayref, and transmits them to
866             the other side of the RMI connection. The _receive() method returns a message
867             type and message data array.
868              
869             Internal to _send() and _receive() the message type and data are passed through
870             _serialize and _deserialize and then transmitted along the writer and reader handles.
871              
872             The _serialize method turns a message_type and message_data into a string value
873             suitable for transmission. Conversely, the _deserialize method turns a string
874             value in the same format into a message_type and message_data array.
875              
876             The serialization process has two stages:
877              
878             =head2 replacing references with identifiers used for remoting
879              
880             An array of message_data of length n to is converted to have a length of n*2.
881             Each value is preceded by an integer which categorizes the value.
882              
883             0 a primitive, non-reference value
884            
885             The value itself follows, it is not a reference, and it is passed by-copy.
886            
887             1 an object reference originating on the sender's side
888            
889             A unique identifier for the object follows instead of the object.
890             The remote side should construct a transparent proxy which uses that ID.
891            
892             2 a non-object (unblessed) reference originating on the sender's side
893            
894             A unique identifier for the reference follows, instead of the reference.
895             The remote side should construct a transparent proxy which uses that ID.
896            
897             3 passing-back a proxy: a reference which originated on the receiver's side
898            
899             The following value is the identifier the remote side sent previously.
900             The remote side should substitue the original object when deserializing
901              
902             4 a serialized object
903              
904             This is the result of serializing the reference. This happens only
905             when explicitly requested. (DBI has some issues with proxies, for instance
906             and has customizations in RMI::Proxy::DBI::db to force serialization of
907             some connection attributes.)
908              
909             See B for more details on forcing serialization.
910              
911             Note that, because the current wire protocol is to use newline as a record
912             separator, we use double-quoted strings to ensure all newlines are escaped.
913              
914             Note that all references are turned into primitives by the above process.
915              
916             =head2 stringification
917              
918             The "wire protocol" for sending and receiving messages is to pass an array via Data::Dumper
919             in such a way that it does not contain newlines. The receiving side uses eval to reconstruct
920             the original message. This is terribly inefficient because the structure does not contain
921             objects of arbitrary depth, and is parsable without tremendous complexity.
922              
923             Details on how proxy objects and references function, and pose as the real item
924             in question, are in B, and B and B
925              
926             =head1 BUGS AND CAVEATS
927              
928             See general bugs in B for general system limitations
929              
930             =head2 the serialization mechanism needs to be made more robust and efficient
931              
932             It's really just enough to "work".
933              
934             The current implementation uses Data::Dumper with options which should remove
935             newlines. Since we do not flatten arbitrary data structures, a simpler parser
936             would be more efficient.
937              
938             The message type is currently a text string. This could be made smaller.
939              
940             The data type before each paramter or return value is an integer, which could
941             also be abbreviated futher, or we could go the other way and be more clear. :)
942              
943             This should switch to sysread and pass the message length instead of relying on
944             buffers, since the non-blocking IO might not have issues.
945              
946             =head1 SEE ALSO
947              
948             B, B, B, B, B
949              
950             B, B, B, B, B
951              
952             =head1 AUTHORS
953              
954             Scott Smith
955              
956             =head1 COPYRIGHT
957              
958             Copyright (c) 2008 - 2009 Scott Smith All rights reserved.
959              
960             =head1 LICENSE
961              
962             This program is free software; you can redistribute it and/or modify it under
963             the same terms as Perl itself.
964              
965             The full text of the license can be found in the LICENSE file included with this
966             module.
967              
968             =cut
969              
970             1;
971