File Coverage

blib/lib/Event/RPC/Server.pm
Criterion Covered Total %
statement 238 297 80.1
branch 47 76 61.8
condition 2 4 50.0
subroutine 65 94 69.1
pod 10 77 12.9
total 362 548 66.0


line stmt bran cond sub pod time code
1             #-----------------------------------------------------------------------
2             # Copyright (C) 2005-2015 by Jörn Reder .
3             # All Rights Reserved. See file COPYRIGHT for details.
4             #
5             # This module is part of Event::RPC, which is free software; you can
6             # redistribute it and/or modify it under the same terms as Perl itself.
7             #-----------------------------------------------------------------------
8              
9             package Event::RPC::Server;
10              
11 34     34   2063054 use Event::RPC;
  34         254  
  34         2260  
12 22     22   15318 use Event::RPC::Connection;
  22         93  
  22         1088  
13 22     22   11745 use Event::RPC::LogConnection;
  22         74  
  22         919  
14 22     22   178 use Event::RPC::Message::Negotiate;
  22         45  
  22         576  
15              
16 22     22   132 use Carp;
  22         46  
  22         1400  
17 22     22   154 use strict;
  22         43  
  22         475  
18 22     22   139 use utf8;
  22         54  
  22         266  
19              
20 22     22   8495 use IO::Socket;
  22         290052  
  22         336  
21 22     22   28490 use Sys::Hostname;
  22         38093  
  22         104533  
22              
23 20     20 0 83 sub get_host { shift->{host} }
24 20     20 0 71 sub get_port { shift->{port} }
25 20     20 0 633 sub get_name { shift->{name} }
26 444     444 0 3307 sub get_loop { shift->{loop} }
27 20     20 0 88 sub get_classes { shift->{classes} }
28 49     49 0 254 sub get_singleton_classes { shift->{singleton_classes} }
29 0     0 0 0 sub get_loaded_classes { shift->{loaded_classes} }
30 68     68 1 648 sub get_clients_connected { shift->{clients_connected} }
31 40     40 1 366 sub get_log_clients_connected { shift->{log_clients_connected} }
32 40     40 0 518 sub get_logging_clients { shift->{logging_clients} }
33 575     575 0 1352 sub get_logger { shift->{logger} }
34 20     20 0 86 sub get_start_log_listener { shift->{start_log_listener} }
35 76     76 0 152 sub get_objects { shift->{objects} }
36 0     0 0 0 sub get_rpc_socket { shift->{rpc_socket} }
37 40     40 0 189 sub get_ssl { shift->{ssl} }
38 6     6 0 24 sub get_ssl_key_file { shift->{ssl_key_file} }
39 6     6 0 25 sub get_ssl_cert_file { shift->{ssl_cert_file} }
40 3     3 0 349 sub get_ssl_passwd_cb { shift->{ssl_passwd_cb} }
41 3     3 0 9 sub get_ssl_opts { shift->{ssl_opts} }
42 125     125 0 1862 sub get_auth_required { shift->{auth_required} }
43 4     4 0 14 sub get_auth_passwd_href { shift->{auth_passwd_href} }
44 11     11 0 56 sub get_auth_module { shift->{auth_module} }
45 20     20 0 165 sub get_listeners_started { shift->{listeners_started} }
46 46     46 0 153 sub get_connection_hook { shift->{connection_hook} }
47 60     60 0 204 sub get_load_modules { shift->{load_modules} }
48 0     0 0 0 sub get_auto_reload_modules { shift->{auto_reload_modules} }
49 3     3 1 2135 sub get_active_connection { shift->{active_connection} }
50 56     56 0 724 sub get_message_formats { shift->{message_formats} }
51 20     20 0 117 sub get_insecure_msg_fmt_ok { shift->{insecure_msg_fmt_ok} }
52              
53 0     0 0 0 sub set_host { shift->{host} = $_[1] }
54 0     0 0 0 sub set_port { shift->{port} = $_[1] }
55 0     0 0 0 sub set_name { shift->{name} = $_[1] }
56 0     0 0 0 sub set_loop { shift->{loop} = $_[1] }
57 0     0 0 0 sub set_classes { shift->{classes} = $_[1] }
58 0     0 0 0 sub set_singleton_classes { shift->{singleton_classes} = $_[1] }
59 0     0 0 0 sub set_loaded_classes { shift->{loaded_classes} = $_[1] }
60 46     46 0 132 sub set_clients_connected { shift->{clients_connected} = $_[1] }
61 40     40 0 97 sub set_log_clients_connected { shift->{log_clients_connected}= $_[1] }
62 0     0 0 0 sub set_logging_clients { shift->{logging_clients} = $_[1] }
63 0     0 0 0 sub set_logger { shift->{logger} = $_[1] }
64 0     0 0 0 sub set_start_log_listener { shift->{start_log_listener} = $_[1] }
65 0     0 0 0 sub set_objects { shift->{objects} = $_[1] }
66 20     20 0 187 sub set_rpc_socket { shift->{rpc_socket} = $_[1] }
67 0     0 0 0 sub set_ssl { shift->{ssl} = $_[1] }
68 0     0 0 0 sub set_ssl_key_file { shift->{ssl_key_file} = $_[1] }
69 0     0 0 0 sub set_ssl_cert_file { shift->{ssl_cert_file} = $_[1] }
70 0     0 0 0 sub set_ssl_passwd_cb { shift->{ssl_passwd_cb} = $_[1] }
71 0     0 0 0 sub set_ssl_opts { shift->{ssl_opts} = $_[1] }
72 0     0 0 0 sub set_auth_required { shift->{auth_required} = $_[1] }
73 0     0 0 0 sub set_auth_passwd_href { shift->{auth_passwd_href} = $_[1] }
74 4     4 0 13 sub set_auth_module { shift->{auth_module} = $_[1] }
75 20     20 0 76 sub set_listeners_started { shift->{listeners_started} = $_[1] }
76 0     0 0 0 sub set_connection_hook { shift->{connection_hook} = $_[1] }
77 0     0 0 0 sub set_load_modules { shift->{load_modules} = $_[1] }
78 0     0 0 0 sub set_auto_reload_modules { shift->{auto_reload_modules} = $_[1] }
79 298     298 0 879 sub set_active_connection { shift->{active_connection} = $_[1] }
80 20     20 0 184 sub set_message_formats { shift->{message_formats} = $_[1] }
81 0     0 0 0 sub set_insecure_msg_fmt_ok { shift->{insecure_msg_fmt_ok} = $_[1] }
82              
83             my $INSTANCE;
84 4     4 1 51 sub instance { $INSTANCE }
85              
86             sub get_max_packet_size {
87 0     0 1 0 return Event::RPC::Message->get_max_packet_size;
88             }
89              
90             sub set_max_packet_size {
91 1     1 1 12 my $class = shift;
92 1         3 my ($value) = @_;
93 1         8 Event::RPC::Message->set_max_packet_size($value);
94             }
95              
96             sub new {
97 20     20 0 66592 my $class = shift;
98 20         1492 my %par = @_;
99             my ($host, $port, $classes, $name, $logger, $start_log_listener) =
100 20         223 @par{'host','port','classes','name','logger','start_log_listener'};
101             my ($ssl, $ssl_key_file, $ssl_cert_file, $ssl_passwd_cb, $ssl_opts) =
102 20         157 @par{'ssl','ssl_key_file','ssl_cert_file','ssl_passwd_cb','ssl_opts'};
103             my ($auth_required, $auth_passwd_href, $auth_module, $loop) =
104 20         170 @par{'auth_required','auth_passwd_href','auth_module','loop'};
105             my ($connection_hook, $auto_reload_modules) =
106 20         137 @par{'connection_hook','auto_reload_modules'};
107             my ($load_modules, $message_formats, $insecure_msg_fmt_ok) =
108 20         152 @par{'load_modules','message_formats','insecure_msg_fmt_ok'};
109              
110 20   50     250 $name ||= "Event-RPC-Server";
111 20 100       89 $insecure_msg_fmt_ok = 1 unless defined $insecure_msg_fmt_ok;
112              
113             #-- for backwards compatibility 'load_modules' defaults to 1
114 20 50       89 if ( !exists $par{load_modules} ) {
115 0         0 $load_modules = 1;
116             }
117              
118 20 50       127 if ( not $loop ) {
119 20         255 foreach my $impl ( qw/AnyEvent Event Glib/ ) {
120 20         70 $loop = "Event::RPC::Loop::$impl";
121 20     20   3101 eval "use $loop";
  20         15681  
  20         768  
  20         741  
122 20 50       126 if ( $@ ) {
123 0         0 $loop = undef;
124             }
125             else {
126 20         163 $loop = $loop->new;
127 20         49 last;
128             }
129             }
130 20 50       155 die "It seems no supported event loop module is installed"
131             unless $loop;
132             }
133              
134 20         1698 my $self = bless {
135             host => $host,
136             port => $port,
137             name => $name,
138             classes => $classes,
139             singleton_classes => {},
140             logger => $logger,
141             start_log_listener => $start_log_listener,
142             loop => $loop,
143              
144             ssl => $ssl,
145             ssl_key_file => $ssl_key_file,
146             ssl_cert_file => $ssl_cert_file,
147             ssl_passwd_cb => $ssl_passwd_cb,
148             ssl_opts => $ssl_opts,
149              
150             auth_required => $auth_required,
151             auth_passwd_href => $auth_passwd_href,
152             auth_module => $auth_module,
153              
154             load_modules => $load_modules,
155             auto_reload_modules => $auto_reload_modules,
156             connection_hook => $connection_hook,
157              
158             message_formats => $message_formats,
159             insecure_msg_fmt_ok => $insecure_msg_fmt_ok,
160              
161             rpc_socket => undef,
162             loaded_classes => {},
163             objects => {},
164             logging_clients => {},
165             clients_connected => 0,
166             listeners_started => 0,
167             log_clients_connected => 0,
168             active_connection => undef,
169             }, $class;
170              
171 20         235 $INSTANCE = $self;
172              
173 20         718 $self->log ($self->get_name." started");
174              
175 20         152 return $self;
176             }
177              
178             sub DESTROY {
179 0     0   0 my $self = shift;
180              
181 0         0 my $rpc_socket = $self->get_rpc_socket;
182 0 0       0 close ($rpc_socket) if $rpc_socket;
183              
184 0         0 1;
185             }
186              
187             sub probe_message_formats {
188 33     33 0 75 my $class = shift;
189 33         223 my ($user_supplied_formats, $insecure_msg_fmt_ok) = @_;
190              
191 33         1031 my $order_lref = Event::RPC::Message::Negotiate->message_format_order;
192 33         173 my $modules_by_name = Event::RPC::Message::Negotiate->known_message_formats;
193              
194 33         182 my %probe_formats;
195 33 100       245 if ( $user_supplied_formats ) {
196 25         240 @probe_formats{@{$user_supplied_formats}} =
197 25         47 (1) x @{$user_supplied_formats};
  25         56  
198             }
199             else {
200 8         15 %probe_formats = %{$modules_by_name};
  8         291  
201             }
202              
203             #-- By default we probe all supported formats, but
204             #-- not Storable. User has to activate this explicitely.
205 33 100       119 if ( not $insecure_msg_fmt_ok ) {
206 3         6 delete $probe_formats{STOR};
207             }
208              
209 33         328 Event::RPC::Message::Negotiate->set_storable_fallback_ok($insecure_msg_fmt_ok);
210              
211 33         42 my @supported_formats;
212 33         51 foreach my $name ( @{$order_lref} ) {
  33         367  
213 132 100       408 next unless $probe_formats{$name};
214              
215 96         361 my $module = $modules_by_name->{$name};
216 96     21   6756 eval "use $module";
  21     21   11633  
  21     21   77  
  21     21   401  
  21         9994  
  0         0  
  0         0  
  21         12074  
  21         207  
  21         433  
  21         9141  
  21         71  
  21         674  
217              
218 96 100       1011 push @supported_formats, $name unless $@;
219             }
220              
221 33         248 return \@supported_formats;
222             }
223              
224             sub setup_listeners {
225 20     20 1 42 my $self = shift;
226              
227             #-- Listener options
228 20         487 my $host = $self->get_host;
229 20         159 my $port = $self->get_port;
230 20 50       250 my @LocalHost = $host ? ( LocalHost => $host ) : ();
231 20   50     74 $host ||= "*";
232              
233             #-- get event loop manager
234 20         92 my $loop = $self->get_loop;
235              
236             #-- setup rpc listener
237 20         65 my $rpc_socket;
238 20 100       119 if ( $self->get_ssl ) {
    50          
239 3         7 eval { require IO::Socket::SSL };
  3         28  
240 3 50       13 croak "SSL requested, but IO::Socket::SSL not installed" if $@;
241 3 50       12 croak "ssl_key_file not set" unless $self->get_ssl_key_file;
242 3 50       12 croak "ssl_cert_file not set" unless $self->get_ssl_cert_file;
243              
244 3         10 my $ssl_opts = $self->get_ssl_opts;
245              
246             $rpc_socket = IO::Socket::SSL->new (
247             Listen => SOMAXCONN,
248             @LocalHost,
249             LocalPort => $port,
250             Proto => 'tcp',
251             ReuseAddr => 1,
252             SSL_key_file => $self->get_ssl_key_file,
253             SSL_cert_file => $self->get_ssl_cert_file,
254             SSL_passwd_cb => $self->get_ssl_passwd_cb,
255 3 50       28 ($ssl_opts?%{$ssl_opts}:()),
  0 50       0  
256             ) or die "can't start SSL RPC listener: $IO::Socket::SSL::ERROR";
257             }
258             elsif ($host eq "unix/") {
259 0         0 require IO::Socket::UNIX;
260 0         0 unlink $port;
261 0 0       0 $rpc_socket = IO::Socket::UNIX->new (
262             Type => IO::Socket::UNIX::SOCK_STREAM(),
263             Listen => SOMAXCONN,
264             Local => $port,
265             ) or die "can't start Unix Domain RPC listener at $port: $!";
266             }
267             else {
268 17         127 require IO::Socket::INET;
269 17 50       737 $rpc_socket = IO::Socket::INET->new (
270             Listen => SOMAXCONN,
271             @LocalHost,
272             LocalPort => $port,
273             Proto => 'tcp',
274             ReuseAddr => 1,
275             ) or die "can't start TCP RPC listener: $!";
276             }
277              
278 20         367344 $self->set_rpc_socket($rpc_socket);
279              
280             $loop->add_io_watcher (
281             fh => $rpc_socket,
282             poll => 'r',
283 24     24   1190418 cb => sub { $self->accept_new_client($rpc_socket); 1 },
  24         9219  
284 20         514 desc => "rpc listener port $port",
285             );
286              
287 20 100       95 if ( $self->get_ssl ) {
288 3         26 $self->log ("Started SSL RPC listener on port $host:$port");
289             } else {
290 17         306 $self->log ("Started RPC listener on $host:$port");
291             }
292              
293             # setup log listener
294 20 50       96 if ( $self->get_start_log_listener ) {
295 20         60 my $log_socket;
296 20 50       83 if ($host eq "unix/") {
297 0         0 $port =~ s/\.sock//;
298 0         0 $port .= ".log.sock";
299 0         0 unlink $port;
300 0 0       0 $log_socket = IO::Socket::UNIX->new (
301             Type => IO::Socket::UNIX::SOCK_STREAM(),
302             Listen => SOMAXCONN,
303             Local => $port,
304             ) or die "can't start Unix Domain log listener at $port: $!";
305             }
306             else {
307 20 50       623 $log_socket = IO::Socket::INET->new (
308             Listen => SOMAXCONN,
309             LocalPort => $port + 1,
310             @LocalHost,
311             Proto => 'tcp',
312             ReuseAddr => 1,
313             ) or die "can't start log listener: $!";
314             }
315              
316             $loop->add_io_watcher (
317             fh => $log_socket,
318             poll => 'r',
319 20     20   3033415 cb => sub { $self->accept_new_log_client($log_socket); 1 },
  20         226  
320 20         8352 desc => "log listener port ".($port+1),
321             );
322              
323 20         137 $self->log ("Started log listener on $host:".($port+1));
324             }
325              
326 20         108 $self->determine_singletons;
327              
328 20         117 $self->set_listeners_started(1);
329              
330 20         52 1;
331             }
332              
333             sub setup_auth_module {
334 20     20 0 54 my $self = shift;
335              
336             #-- Exit if no auth is required or setup already
337 20 100       85 return if not $self->get_auth_required;
338 4 50       27 return if $self->get_auth_module;
339              
340             #-- Default to Event::RPC::AuthPasswdHash
341 4         2390 require Event::RPC::AuthPasswdHash;
342              
343             #-- Setup an instance
344 4         28 my $passwd_href = $self->get_auth_passwd_href;
345 4         49 my $auth_module = Event::RPC::AuthPasswdHash->new ($passwd_href);
346 4         23 $self->set_auth_module($auth_module);
347              
348 4         9 1;
349             }
350              
351             sub prepare {
352 20     20 0 41 my $self = shift;
353              
354 20 50       89 $self->setup_listeners
355             unless $self->get_listeners_started;
356              
357 20         107 $self->setup_auth_module;
358              
359             #-- Filter unsupported message formats
360 20         106 $self->set_message_formats(
361             $self->probe_message_formats(
362             $self->get_message_formats,
363             $self->get_insecure_msg_fmt_ok
364             )
365             );
366              
367 20         199 1;
368             }
369              
370             sub start {
371 20     20 1 533 my $self = shift;
372              
373             #-- Prepare server for startup
374 20         127 $self->prepare;
375              
376 20         93 my $loop = $self->get_loop;
377              
378 20         186 $self->log ("Enter main loop using ".ref($loop));
379              
380 20         109 $loop->enter;
381              
382 20         98 $self->log ("Server stopped");
383              
384 20         467 1;
385             }
386              
387             sub stop {
388 20     20 1 236 my $self = shift;
389              
390 20         80 $self->get_loop->leave;
391              
392 20         78 1;
393             }
394              
395             sub determine_singletons {
396 20     20 0 43 my $self = shift;
397              
398 20         85 my $classes = $self->get_classes;
399 20         77 my $singleton_classes = $self->get_singleton_classes;
400              
401 20         59 foreach my $class ( keys %{$classes} ) {
  20         109  
402 40         95 foreach my $method ( keys %{$classes->{$class}} ) {
  40         205  
403             # check for singleton returner
404 283 100       919 if ( $classes->{$class}->{$method} eq '_singleton' ) {
405             # change to constructor
406 20         52 $classes->{$class}->{$method} = '_constructor';
407             # track that this class is a singleton
408 20         77 $singleton_classes->{$class} = 1;
409 20         839 last;
410             }
411             }
412             }
413              
414 20         66 1;
415             }
416              
417             sub accept_new_client {
418 24     24 0 91 my $self = shift;
419 24         80 my ($rpc_socket) = @_;
420              
421 24 100       410 my $client_socket = $rpc_socket->accept or return;
422              
423 23         45027 Event::RPC::Connection->new ($self, $client_socket);
424              
425 23         108 $self->set_clients_connected ( 1 + $self->get_clients_connected );
426              
427 23         281 1;
428             }
429              
430             sub accept_new_log_client {
431 20     20 0 98 my $self = shift;
432 20         88 my ($log_socket) = @_;
433              
434 20 50       691 my $client_socket = $log_socket->accept or return;
435              
436 20         7685 my $log_client =
437             Event::RPC::LogConnection->new($self, $client_socket);
438              
439 20         133 $self->set_log_clients_connected ( 1 + $self->get_log_clients_connected );
440 20         92 $self->get_logging_clients->{$log_client->get_cid} = $log_client;
441 20 50       103 $self->get_logger->add_fh($client_socket)
442             if $self->get_logger;
443              
444 20         94 $self->log(2, "New log client connected");
445              
446 20         227 1;
447             }
448              
449             sub load_class {
450 0     0 0 0 my $self = shift;
451 0         0 my ($class) = @_;
452              
453 0         0 Event::RPC::Connection->new ($self)->load_class($class);
454              
455 0         0 return $class;
456             }
457              
458             sub log {
459 535     535 1 1073 my $self = shift;
460 535         1914 my $logger = $self->get_logger;
461 535 50       4211 return unless $logger;
462 0         0 $logger->log(@_);
463 0         0 1;
464             }
465              
466             sub remove_object {
467 8     8 0 21 my $self = shift;
468 8         21 my ($object) = @_;
469              
470 8         28 my $objects = $self->get_objects;
471              
472 8 50       39 if ( not $objects->{"$object"} ) {
473 0         0 warn "Object $object not registered";
474 0         0 return;
475             }
476              
477 8         78 delete $objects->{"$object"};
478              
479 8         43 $self->log(5, "Object '$object' removed");
480              
481 8         17 1;
482             }
483              
484             sub register_object {
485 39     39 0 64 my $self = shift;
486 39         91 my ($object, $class) = @_;
487              
488 39         179 my $objects = $self->get_objects;
489              
490 39         54 my $refcount;
491 39 100       325 if ( $objects->{"$object"} ) {
492 10         39 $refcount = ++$objects->{"$object"}->{refcount};
493             } else {
494 29         54 $refcount = 1;
495 29         389 $objects->{"$object"} = {
496             object => $object,
497             class => $class,
498             refcount => 1,
499             };
500             }
501              
502 39         180 $self->log(5, "Object '$object' registered. Refcount=$refcount");
503              
504 39         82 1;
505             }
506              
507             sub deregister_object {
508 29     29 0 52 my $self = shift;
509 29         141 my ($object) = @_;
510              
511 29         87 my $objects = $self->get_objects;
512              
513 29 50       117 if ( not $objects->{"$object"} ) {
514 0         0 warn "Object $object not registered";
515 0         0 return;
516             }
517              
518 29         82 my $refcount = --$objects->{"$object"}->{refcount};
519              
520 29         121 my ($class) = split(/=/, $object);
521 29 100       104 if ( $self->get_singleton_classes->{$class} ) {
522             # never deregister singletons
523 21         112 $self->log(4, "Skip deregistration of singleton '$object'");
524 21         57 return;
525             }
526              
527 8         58 $self->log(5, "Object '$object' deregistered. Refcount=$refcount");
528              
529 8 50       55 $self->remove_object($object) if $refcount == 0;
530              
531 8         28 1;
532             }
533              
534             sub print_object_register {
535 0     0 0 0 my $self = shift;
536              
537 0         0 print "-"x70,"\n";
538              
539 0         0 my $objects = $self->get_objects;
540 0         0 foreach my $oid ( sort keys %{$objects} ) {
  0         0  
541 0         0 print "$oid\t$objects->{$oid}->{refcount}\n";
542             }
543              
544 0         0 1;
545             }
546              
547             1;
548              
549             __END__