| 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::Client; | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 67 |  |  | 67 |  | 741968 | use Event::RPC; | 
|  | 67 |  |  |  |  | 259 |  | 
|  | 67 |  |  |  |  | 1990 |  | 
| 12 | 31 |  |  | 31 |  | 5677 | use Event::RPC::Message::Negotiate; | 
|  | 31 |  |  |  |  | 45 |  | 
|  | 31 |  |  |  |  | 605 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 31 |  |  | 31 |  | 155 | use Carp; | 
|  | 31 |  |  |  |  | 48 |  | 
|  | 31 |  |  |  |  | 1264 |  | 
| 15 | 31 |  |  | 31 |  | 119 | use strict; | 
|  | 31 |  |  |  |  | 57 |  | 
|  | 31 |  |  |  |  | 576 |  | 
| 16 | 31 |  |  | 31 |  | 110 | use utf8; | 
|  | 31 |  |  |  |  | 53 |  | 
|  | 31 |  |  |  |  | 132 |  | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 31 |  |  | 31 |  | 4536 | use IO::Socket::INET; | 
|  | 31 |  |  |  |  | 148237 |  | 
|  | 31 |  |  |  |  | 277 |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | #-- This can be changed for testing purposes e.g. to simulate | 
| 21 |  |  |  |  |  |  | #-- old clients connecting straight with Storable format. | 
| 22 |  |  |  |  |  |  | $Event::RPC::Client::DEFAULT_MESSAGE_FORMAT = "Event::RPC::Message::Negotiate"; | 
| 23 |  |  |  |  |  |  |  | 
| 24 | 79 |  |  | 79 | 1 | 612 | sub get_client_version          { $Event::RPC::VERSION                  } | 
| 25 | 79 |  |  | 79 | 1 | 795 | sub get_client_protocol         { $Event::RPC::PROTOCOL                 } | 
| 26 |  |  |  |  |  |  |  | 
| 27 | 0 |  |  | 0 | 0 | 0 | sub get_host                    { shift->{host}                         } | 
| 28 | 91 |  |  | 91 | 0 | 542 | sub get_port                    { shift->{port}                         } | 
| 29 | 989 |  |  | 989 | 0 | 11265 | sub get_sock                    { shift->{sock}                         } | 
| 30 | 91 |  |  | 91 | 0 | 284 | sub get_timeout                 { shift->{timeout}                      } | 
| 31 | 76 |  |  | 76 | 0 | 316 | sub get_classes                 { shift->{classes}                      } | 
| 32 | 152 |  |  | 152 | 0 | 510 | sub get_class_map               { shift->{class_map}                    } | 
| 33 | 152 |  |  | 152 | 0 | 494 | sub get_loaded_classes          { shift->{loaded_classes}               } | 
| 34 | 7 |  |  | 7 | 0 | 56 | sub get_error_cb                { shift->{error_cb}                     } | 
| 35 | 91 |  |  | 91 | 0 | 358 | sub get_ssl                     { shift->{ssl}                          } | 
| 36 | 12 |  |  | 12 | 0 | 51 | sub get_ssl_ca_file             { shift->{ssl_ca_file}                  } | 
| 37 | 7 |  |  | 7 | 0 | 40 | sub get_ssl_ca_path             { shift->{ssl_ca_path}                  } | 
| 38 | 7 |  |  | 7 | 0 | 17 | sub get_ssl_opts                { shift->{ssl_opts}                     } | 
| 39 | 79 |  |  | 79 | 0 | 207 | sub get_auth_user               { shift->{auth_user}                    } | 
| 40 | 79 |  |  | 79 | 0 | 168 | sub get_auth_pass               { shift->{auth_pass}                    } | 
| 41 | 301 |  |  | 301 | 0 | 64976 | sub get_connected               { shift->{connected}                    } | 
| 42 | 91 |  |  | 91 | 0 | 332 | sub get_server                  { shift->{server}                       } | 
| 43 | 0 |  |  | 0 | 1 | 0 | sub get_server_version          { shift->{server_version}               } | 
| 44 | 0 |  |  | 0 | 1 | 0 | sub get_server_protocol         { shift->{server_protocol}              } | 
| 45 | 962 |  |  | 962 | 0 | 24427 | sub get_message_format          { shift->{message_format}               } | 
| 46 | 76 |  |  | 76 | 0 | 1908 | sub get_insecure_msg_fmt_ok     { shift->{insecure_msg_fmt_ok}          } | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 0 |  |  | 0 | 0 | 0 | sub set_host                    { shift->{host}                 = $_[1] } | 
| 49 | 0 |  |  | 0 | 0 | 0 | sub set_port                    { shift->{port}                 = $_[1] } | 
| 50 | 89 |  |  | 89 | 0 | 923 | sub set_sock                    { shift->{sock}                 = $_[1] } | 
| 51 | 0 |  |  | 0 | 0 | 0 | sub set_timeout                 { shift->{timeout}              = $_[1] } | 
| 52 | 0 |  |  | 0 | 0 | 0 | sub set_classes                 { shift->{classes}              = $_[1] } | 
| 53 | 0 |  |  | 0 | 0 | 0 | sub set_class_map               { shift->{class_map}            = $_[1] } | 
| 54 | 0 |  |  | 0 | 0 | 0 | sub set_loaded_classes          { shift->{loaded_classes}       = $_[1] } | 
| 55 | 0 |  |  | 0 | 0 | 0 | sub set_error_cb                { shift->{error_cb}             = $_[1] } | 
| 56 | 0 |  |  | 0 | 0 | 0 | sub set_ssl                     { shift->{ssl}                  = $_[1] } | 
| 57 | 1 |  |  | 1 | 0 | 6960 | sub set_ssl_ca_file             { shift->{ssl_ca_file}          = $_[1] } | 
| 58 | 0 |  |  | 0 | 0 | 0 | sub set_ssl_ca_path             { shift->{ssl_ca_path}          = $_[1] } | 
| 59 | 0 |  |  | 0 | 0 | 0 | sub set_ssl_opts                { shift->{ssl_opts}             = $_[1] } | 
| 60 | 0 |  |  | 0 | 0 | 0 | sub set_auth_user               { shift->{auth_user}            = $_[1] } | 
| 61 | 3 |  |  | 3 | 0 | 12 | sub set_auth_pass               { shift->{auth_pass}            = $_[1] } | 
| 62 | 229 |  |  | 229 | 0 | 1568 | sub set_connected               { shift->{connected}            = $_[1] } | 
| 63 | 0 |  |  | 0 | 0 | 0 | sub set_server                  { shift->{server}               = $_[1] } | 
| 64 | 79 |  |  | 79 | 0 | 865 | sub set_server_version          { shift->{server_version}       = $_[1] } | 
| 65 | 79 |  |  | 79 | 0 | 706 | sub set_server_protocol         { shift->{server_protocol}      = $_[1] } | 
| 66 | 153 |  |  | 153 | 0 | 428 | sub set_message_format          { shift->{message_format}       = $_[1] } | 
| 67 | 0 |  |  | 0 | 0 | 0 | sub set_insecure_msg_fmt_ok     { shift->{insecure_msg_fmt_ok}  = $_[1] } | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | sub get_max_packet_size { | 
| 70 | 1 |  |  | 1 | 1 | 6 | return Event::RPC::Message->get_max_packet_size; | 
| 71 |  |  |  |  |  |  | } | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | sub set_max_packet_size { | 
| 74 | 1 |  |  | 1 | 1 | 1504 | my $class = shift; | 
| 75 | 1 |  |  |  |  | 4 | my ($value) = @_; | 
| 76 | 1 |  |  |  |  | 6 | Event::RPC::Message->set_max_packet_size($value); | 
| 77 |  |  |  |  |  |  | } | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | sub new { | 
| 80 | 87 |  |  | 87 | 0 | 53752 | my $class = shift; | 
| 81 | 87 |  |  |  |  | 1531 | my %par   = @_; | 
| 82 |  |  |  |  |  |  | my  ($server, $host, $port, $classes, $class_map, $error_cb, $timeout) = | 
| 83 | 87 |  |  |  |  | 749 | @par{'server','host','port','classes','class_map','error_cb','timeout'}; | 
| 84 |  |  |  |  |  |  | my  ($ssl, $ssl_ca_file, $ssl_opts, $auth_user, $auth_pass, $insecure_msg_fmt_ok) = | 
| 85 | 87 |  |  |  |  | 832 | @par{'ssl','ssl_ca_file','ssl_opts','auth_user','auth_pass','insecure_msg_fmt_ok'}; | 
| 86 |  |  |  |  |  |  |  | 
| 87 | 87 |  | 50 |  |  | 2387 | $server ||= ''; | 
| 88 | 87 |  | 50 |  |  | 856 | $host   ||= ''; | 
| 89 | 87 | 100 |  |  |  | 936 | $insecure_msg_fmt_ok = 1 unless defined $insecure_msg_fmt_ok; | 
| 90 |  |  |  |  |  |  |  | 
| 91 | 87 | 50 | 33 |  |  | 908 | if ( $server ne '' and $host eq '' ) { | 
| 92 | 0 |  |  |  |  | 0 | warn "Option 'server' is deprecated. Use 'host' instead."; | 
| 93 | 0 |  |  |  |  | 0 | $host = $server; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 87 |  |  |  |  | 6420 | my $self = bless { | 
| 97 |  |  |  |  |  |  | host                => $server, | 
| 98 |  |  |  |  |  |  | server              => $host, | 
| 99 |  |  |  |  |  |  | port                => $port, | 
| 100 |  |  |  |  |  |  | timeout             => $timeout, | 
| 101 |  |  |  |  |  |  | classes             => $classes, | 
| 102 |  |  |  |  |  |  | class_map           => $class_map, | 
| 103 |  |  |  |  |  |  | ssl                 => $ssl, | 
| 104 |  |  |  |  |  |  | ssl_ca_file         => $ssl_ca_file, | 
| 105 |  |  |  |  |  |  | ssl_opts            => $ssl_opts, | 
| 106 |  |  |  |  |  |  | auth_user           => $auth_user, | 
| 107 |  |  |  |  |  |  | auth_pass           => $auth_pass, | 
| 108 |  |  |  |  |  |  | error_cb            => $error_cb, | 
| 109 |  |  |  |  |  |  | message_format      => $Event::RPC::Client::DEFAULT_MESSAGE_FORMAT, | 
| 110 |  |  |  |  |  |  | insecure_msg_fmt_ok => $insecure_msg_fmt_ok, | 
| 111 |  |  |  |  |  |  | loaded_classes      => {}, | 
| 112 |  |  |  |  |  |  | connected           => 0, | 
| 113 |  |  |  |  |  |  | }, $class; | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 87 |  |  |  |  | 700 | return $self; | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | sub connect { | 
| 119 | 91 |  |  | 91 | 1 | 805 | my $self = shift; | 
| 120 |  |  |  |  |  |  |  | 
| 121 | 91 | 50 |  |  |  | 1862 | croak "Client is already connected" if $self->get_connected; | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 91 |  |  |  |  | 1190 | my $ssl     = $self->get_ssl; | 
| 124 | 91 |  |  |  |  | 413 | my $server  = $self->get_server; | 
| 125 | 91 |  |  |  |  | 698 | my $port    = $self->get_port; | 
| 126 | 91 |  |  |  |  | 557 | my $timeout = $self->get_timeout; | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 91 |  |  |  |  | 489 | $self->set_message_format($Event::RPC::Client::DEFAULT_MESSAGE_FORMAT); | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | #-- Client may try to fallback to Storable | 
| 131 | 91 | 100 | 100 |  |  | 412 | Event::RPC::Message::Negotiate->set_storable_fallback_ok(1) | 
| 132 |  |  |  |  |  |  | if $self->get_message_format eq 'Event::RPC::Message::Negotiate' and | 
| 133 |  |  |  |  |  |  | $self->get_insecure_msg_fmt_ok; | 
| 134 |  |  |  |  |  |  |  | 
| 135 | 91 | 100 |  |  |  | 414 | if ( $ssl ) { | 
| 136 | 7 |  |  |  |  | 21 | eval { require IO::Socket::SSL }; | 
|  | 7 |  |  |  |  | 114 |  | 
| 137 | 7 | 50 |  |  |  | 33 | croak "SSL requested, but IO::Socket::SSL not installed" if $@; | 
| 138 |  |  |  |  |  |  | } | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 91 |  |  |  |  | 206 | my $sock; | 
| 141 | 91 | 100 |  |  |  | 305 | if ( $ssl ) { | 
| 142 | 7 |  |  |  |  | 13 | my @verify_opts; | 
| 143 | 7 | 100 | 66 |  |  | 32 | if ( $self->get_ssl_ca_file or $self->get_ssl_ca_path ) { | 
| 144 | 5 |  |  |  |  | 16 | push @verify_opts, ( | 
| 145 |  |  |  |  |  |  | SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER(), | 
| 146 |  |  |  |  |  |  | SSL_ca_file     => $self->get_ssl_ca_file, | 
| 147 |  |  |  |  |  |  | SSL_ca_path     => $self->get_ssl_ca_path, | 
| 148 |  |  |  |  |  |  | ); | 
| 149 |  |  |  |  |  |  | } | 
| 150 |  |  |  |  |  |  | else { | 
| 151 | 2 |  |  |  |  | 6 | push @verify_opts, ( | 
| 152 |  |  |  |  |  |  | SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(), | 
| 153 |  |  |  |  |  |  | ); | 
| 154 |  |  |  |  |  |  | } | 
| 155 |  |  |  |  |  |  |  | 
| 156 | 7 |  |  |  |  | 28 | my $ssl_opts = $self->get_ssl_opts; | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | $sock = IO::Socket::SSL->new( | 
| 159 |  |  |  |  |  |  | Proto    => 'tcp', | 
| 160 |  |  |  |  |  |  | PeerPort => $port, | 
| 161 |  |  |  |  |  |  | PeerAddr => $server, | 
| 162 |  |  |  |  |  |  | Type     => SOCK_STREAM, | 
| 163 |  |  |  |  |  |  | Timeout  => $timeout, | 
| 164 |  |  |  |  |  |  | @verify_opts, | 
| 165 | 7 | 50 |  |  |  | 229 | ($ssl_opts?%{$ssl_opts}:()), | 
|  | 0 | 100 |  |  |  | 0 |  | 
| 166 |  |  |  |  |  |  | ) | 
| 167 |  |  |  |  |  |  | or croak "Can't open SSL connection to $server:$port: $IO::Socket::SSL::ERROR"; | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  | else { | 
| 170 | 84 | 50 |  |  |  | 714 | $sock = IO::Socket::INET->new( | 
| 171 |  |  |  |  |  |  | Proto    => 'tcp', | 
| 172 |  |  |  |  |  |  | PeerPort => $port, | 
| 173 |  |  |  |  |  |  | PeerAddr => $server, | 
| 174 |  |  |  |  |  |  | Type     => SOCK_STREAM, | 
| 175 |  |  |  |  |  |  | Timeout  => $timeout, | 
| 176 |  |  |  |  |  |  | ) | 
| 177 |  |  |  |  |  |  | or croak "Can't open connection to $server:$port - $!"; | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 89 |  |  |  |  | 99444 | $sock->autoflush(1); | 
| 181 |  |  |  |  |  |  |  | 
| 182 | 89 |  |  |  |  | 4520 | $self->set_sock($sock); | 
| 183 |  |  |  |  |  |  |  | 
| 184 | 89 |  |  |  |  | 900 | eval { | 
| 185 |  |  |  |  |  |  | #-- Perform message format negotitation if we are not | 
| 186 |  |  |  |  |  |  | #-- configured to a specific format already. | 
| 187 | 89 | 100 |  |  |  | 333 | $self->negotiate_message_format | 
| 188 |  |  |  |  |  |  | if $self->get_message_format eq 'Event::RPC::Message::Negotiate'; | 
| 189 |  |  |  |  |  |  |  | 
| 190 | 86 |  |  |  |  | 763 | $self->check_version; | 
| 191 |  |  |  |  |  |  | }; | 
| 192 |  |  |  |  |  |  |  | 
| 193 | 89 | 100 |  |  |  | 327 | if ( $@ ) { | 
| 194 | 10 |  |  |  |  | 72 | $self->disconnect; | 
| 195 | 10 |  |  |  |  | 88 | die $@; | 
| 196 |  |  |  |  |  |  | } | 
| 197 |  |  |  |  |  |  |  | 
| 198 | 79 |  |  |  |  | 336 | my $auth_user = $self->get_auth_user; | 
| 199 | 79 |  |  |  |  | 237 | my $auth_pass = $self->get_auth_pass; | 
| 200 |  |  |  |  |  |  |  | 
| 201 | 79 | 100 |  |  |  | 244 | if ( $auth_user ) { | 
| 202 | 7 |  |  |  |  | 58 | my $rc = $self->send_request( | 
| 203 |  |  |  |  |  |  | {   cmd  => 'auth', | 
| 204 |  |  |  |  |  |  | user => $auth_user, | 
| 205 |  |  |  |  |  |  | pass => $auth_pass, | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | ); | 
| 208 | 4 | 50 |  |  |  | 35 | if ( not $rc->{ok} ) { | 
| 209 | 0 |  |  |  |  | 0 | $self->disconnect; | 
| 210 | 0 |  |  |  |  | 0 | croak $rc->{msg}; | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  | } | 
| 213 |  |  |  |  |  |  |  | 
| 214 | 76 | 50 |  |  |  | 343 | if ( not $self->get_classes ) { | 
| 215 | 76 |  |  |  |  | 685 | $self->load_all_classes; | 
| 216 |  |  |  |  |  |  | } | 
| 217 |  |  |  |  |  |  | else { | 
| 218 | 0 |  |  |  |  | 0 | $self->load_classes; | 
| 219 |  |  |  |  |  |  | } | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 76 |  |  |  |  | 319 | $self->set_connected(1); | 
| 222 |  |  |  |  |  |  |  | 
| 223 | 76 |  |  |  |  | 244 | 1; | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | sub log_connect { | 
| 227 | 174 |  |  | 174 | 0 | 48209359 | my $class = shift; | 
| 228 | 174 |  |  |  |  | 4589 | my %par   = @_; | 
| 229 | 174 |  |  |  |  | 2015 | my ( $server, $port ) = @par{ 'server', 'port' }; | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 174 | 100 |  |  |  | 6914 | my $sock = IO::Socket::INET->new( | 
| 232 |  |  |  |  |  |  | Proto    => 'tcp', | 
| 233 |  |  |  |  |  |  | PeerPort => $port, | 
| 234 |  |  |  |  |  |  | PeerAddr => $server, | 
| 235 |  |  |  |  |  |  | Type     => SOCK_STREAM | 
| 236 |  |  |  |  |  |  | ) | 
| 237 |  |  |  |  |  |  | or croak "Can't open connection to $server:$port - $!"; | 
| 238 |  |  |  |  |  |  |  | 
| 239 | 87 |  |  |  |  | 69635 | return $sock; | 
| 240 |  |  |  |  |  |  | } | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | sub disconnect { | 
| 243 | 153 |  |  | 153 | 1 | 15509 | my $self = shift; | 
| 244 |  |  |  |  |  |  |  | 
| 245 | 153 | 100 |  |  |  | 474 | close( $self->get_sock ) if $self->get_sock; | 
| 246 | 153 |  |  |  |  | 1758 | $self->set_connected(0); | 
| 247 |  |  |  |  |  |  |  | 
| 248 | 153 |  |  |  |  | 2216 | 1; | 
| 249 |  |  |  |  |  |  | } | 
| 250 |  |  |  |  |  |  |  | 
| 251 |  |  |  |  |  |  | sub DESTROY { | 
| 252 | 67 |  |  | 67 |  | 10167540 | shift->disconnect; | 
| 253 |  |  |  |  |  |  | } | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | sub error { | 
| 256 | 7 |  |  | 7 | 0 | 56 | my $self = shift; | 
| 257 | 7 |  |  |  |  | 35 | my ($message) = @_; | 
| 258 |  |  |  |  |  |  |  | 
| 259 | 7 |  |  |  |  | 91 | my $error_cb = $self->get_error_cb; | 
| 260 |  |  |  |  |  |  |  | 
| 261 | 7 | 50 |  |  |  | 70 | if ($error_cb) { | 
| 262 | 0 |  |  |  |  | 0 | &$error_cb( $self, $message ); | 
| 263 |  |  |  |  |  |  | } | 
| 264 |  |  |  |  |  |  | else { | 
| 265 | 7 |  |  |  |  | 56 | die "Unhandled error in client/server communication: $message"; | 
| 266 |  |  |  |  |  |  | } | 
| 267 |  |  |  |  |  |  |  | 
| 268 | 0 |  |  |  |  | 0 | 1; | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | sub negotiate_message_format { | 
| 272 | 65 |  |  | 65 | 0 | 171 | my $self = shift; | 
| 273 |  |  |  |  |  |  |  | 
| 274 | 65 |  |  |  |  | 175 | my $rc = eval { | 
| 275 | 65 |  |  |  |  | 1528 | $self->send_request({ | 
| 276 |  |  |  |  |  |  | cmd => "neg_formats_avail" | 
| 277 |  |  |  |  |  |  | }) | 
| 278 |  |  |  |  |  |  | }; | 
| 279 |  |  |  |  |  |  |  | 
| 280 | 65 | 100 |  |  |  | 584 | if ( $@ ) { | 
| 281 |  |  |  |  |  |  | #-- On error we probably may fall back to Storable | 
| 282 |  |  |  |  |  |  | #-- (we connected to an old server) | 
| 283 | 9 | 100 |  |  |  | 63 | if ( $self->get_insecure_msg_fmt_ok ) { | 
| 284 | 6 |  |  |  |  | 30 | require Event::RPC::Message::Storable; | 
| 285 | 6 |  |  |  |  | 36 | $self->set_message_format("Event::RPC::Message::Storable"); | 
| 286 | 6 |  |  |  |  | 30 | return; | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | #-- die if Storable is not allowed | 
| 290 | 3 |  |  |  |  | 42 | die "Error on message format negotiation and client is not ". | 
| 291 |  |  |  |  |  |  | "allowed to fall back to Storable\n"; | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  |  | 
| 294 | 56 |  |  |  |  | 316 | my $modules_by_format_name = | 
| 295 |  |  |  |  |  |  | Event::RPC::Message::Negotiate->known_message_formats; | 
| 296 |  |  |  |  |  |  |  | 
| 297 | 56 |  |  |  |  | 500 | my @formats = split(/,/, $rc->{msg}); | 
| 298 |  |  |  |  |  |  |  | 
| 299 | 56 |  |  |  |  | 291 | my $format_chosen = ''; | 
| 300 | 56 |  |  |  |  | 402 | my $module_chosen = ''; | 
| 301 | 56 |  |  |  |  | 525 | foreach my $format ( @formats ) { | 
| 302 | 56 | 50 |  |  |  | 457 | my $module = $modules_by_format_name->{$format} | 
| 303 |  |  |  |  |  |  | or die "Unknown message format '$format"; | 
| 304 |  |  |  |  |  |  |  | 
| 305 | 56 |  |  | 20 |  | 8960 | eval "use $module"; | 
|  | 20 |  |  |  |  | 6036 |  | 
|  | 20 |  |  |  |  | 62 |  | 
|  | 20 |  |  |  |  | 506 |  | 
| 306 |  |  |  |  |  |  |  | 
| 307 | 56 | 50 |  |  |  | 339 | if ( not $@ ) { | 
| 308 | 56 |  |  |  |  | 160 | $format_chosen = $format; | 
| 309 | 56 |  |  |  |  | 120 | $module_chosen = $module; | 
| 310 | 56 |  |  |  |  | 153 | last; | 
| 311 |  |  |  |  |  |  | }; | 
| 312 |  |  |  |  |  |  | } | 
| 313 |  |  |  |  |  |  |  | 
| 314 | 56 | 50 |  |  |  | 188 | die "Can't negotiate message format\n" unless $format_chosen; | 
| 315 |  |  |  |  |  |  |  | 
| 316 | 56 |  |  |  |  | 161 | eval { | 
| 317 | 56 |  |  |  |  | 361 | $self->send_request({ | 
| 318 |  |  |  |  |  |  | cmd => "neg_format_set", | 
| 319 |  |  |  |  |  |  | msg => $format_chosen, | 
| 320 |  |  |  |  |  |  | }) | 
| 321 |  |  |  |  |  |  | }; | 
| 322 |  |  |  |  |  |  |  | 
| 323 | 56 | 50 |  |  |  | 240 | die "Error on neg_format_set: $@" if $@; | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 56 |  |  |  |  | 239 | $self->set_message_format($module_chosen); | 
| 326 |  |  |  |  |  |  |  | 
| 327 | 56 |  |  |  |  | 179 | 1; | 
| 328 |  |  |  |  |  |  | } | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  | sub check_version { | 
| 331 | 86 |  |  | 86 | 0 | 220 | my $self = shift; | 
| 332 |  |  |  |  |  |  |  | 
| 333 | 86 |  |  |  |  | 282 | my $rc = eval { $self->send_request( { cmd => 'version', } ) }; | 
|  | 86 |  |  |  |  | 924 |  | 
| 334 | 86 | 100 |  |  |  | 493 | die "CATCHED $@" if $@; | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 79 |  |  |  |  | 465 | $self->set_server_version( $rc->{version} ); | 
| 337 | 79 |  |  |  |  | 428 | $self->set_server_protocol( $rc->{protocol} ); | 
| 338 |  |  |  |  |  |  |  | 
| 339 | 79 | 50 |  |  |  | 433 | if ( $rc->{version} ne $self->get_client_version ) { | 
| 340 | 0 |  |  |  |  | 0 | warn "Event::RPC warning: server version $rc->{version} != " | 
| 341 |  |  |  |  |  |  | . "client version " | 
| 342 |  |  |  |  |  |  | . $self->get_client_version; | 
| 343 |  |  |  |  |  |  | } | 
| 344 |  |  |  |  |  |  |  | 
| 345 | 79 | 50 |  |  |  | 690 | if ( $rc->{protocol} < $self->get_client_protocol ) { | 
| 346 | 0 |  |  |  |  | 0 | die "FATAL: Server protocol version $rc->{protocol} < " | 
| 347 |  |  |  |  |  |  | . "client protocol version " | 
| 348 |  |  |  |  |  |  | . $self->get_client_protocol; | 
| 349 |  |  |  |  |  |  | } | 
| 350 |  |  |  |  |  |  |  | 
| 351 | 79 |  |  |  |  | 401 | 1; | 
| 352 |  |  |  |  |  |  | } | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | sub load_all_classes { | 
| 355 | 76 |  |  | 76 | 0 | 221 | my $self = shift; | 
| 356 |  |  |  |  |  |  |  | 
| 357 | 76 |  |  |  |  | 574 | my $rc = $self->send_request( { cmd => 'class_info_all', } ); | 
| 358 |  |  |  |  |  |  |  | 
| 359 | 76 |  |  |  |  | 265 | my $class_info_all = $rc->{class_info_all}; | 
| 360 |  |  |  |  |  |  |  | 
| 361 | 76 |  |  |  |  | 459 | foreach my $class ( keys %{$class_info_all} ) { | 
|  | 76 |  |  |  |  | 935 |  | 
| 362 | 152 |  |  |  |  | 823 | $self->load_class( $class, $class_info_all->{$class} ); | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  |  | 
| 365 | 76 |  |  |  |  | 450 | 1; | 
| 366 |  |  |  |  |  |  | } | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | sub load_classes { | 
| 369 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 370 |  |  |  |  |  |  |  | 
| 371 | 0 |  |  |  |  | 0 | my $classes = $self->get_classes; | 
| 372 | 0 |  |  |  |  | 0 | my %classes; | 
| 373 | 0 |  |  |  |  | 0 | @classes{ @{$classes} } = (1) x @{$classes}; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 0 |  |  |  |  | 0 | my $rc = $self->send_request( { cmd => 'classes_list', } ); | 
| 376 |  |  |  |  |  |  |  | 
| 377 | 0 |  |  |  |  | 0 | foreach my $class ( @{ $rc->{classes} } ) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 378 | 0 | 0 |  |  |  | 0 | next if not $classes{$class}; | 
| 379 | 0 |  |  |  |  | 0 | $classes{$class} = 0; | 
| 380 |  |  |  |  |  |  |  | 
| 381 | 0 |  |  |  |  | 0 | my $rc = $self->send_request( | 
| 382 |  |  |  |  |  |  | {   cmd   => 'class_info', | 
| 383 |  |  |  |  |  |  | class => $class, | 
| 384 |  |  |  |  |  |  | } | 
| 385 |  |  |  |  |  |  | ); | 
| 386 |  |  |  |  |  |  |  | 
| 387 | 0 |  |  |  |  | 0 | $self->load_class( $class, $rc->{methods} ); | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  |  | 
| 390 | 0 |  |  |  |  | 0 | foreach my $class ( @{$classes} ) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 391 |  |  |  |  |  |  | warn "WARNING: Class '$class' not exported by server" | 
| 392 | 0 | 0 |  |  |  | 0 | if $classes{$class}; | 
| 393 |  |  |  |  |  |  | } | 
| 394 |  |  |  |  |  |  |  | 
| 395 | 0 |  |  |  |  | 0 | 1; | 
| 396 |  |  |  |  |  |  | } | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | sub load_class { | 
| 399 | 152 |  |  | 152 | 0 | 367 | my $self = shift; | 
| 400 | 152 |  |  |  |  | 382 | my ( $class, $methods ) = @_; | 
| 401 |  |  |  |  |  |  |  | 
| 402 | 152 |  |  |  |  | 659 | my $loaded_classes = $self->get_loaded_classes; | 
| 403 | 152 | 50 |  |  |  | 535 | return 1 if $loaded_classes->{$class}; | 
| 404 | 152 |  |  |  |  | 351 | $loaded_classes->{$class} = 1; | 
| 405 |  |  |  |  |  |  |  | 
| 406 | 152 |  |  |  |  | 236 | my $local_method; | 
| 407 | 152 |  |  |  |  | 606 | my $class_map   = $self->get_class_map; | 
| 408 | 152 |  | 33 |  |  | 1259 | my $local_class = $class_map->{$class} || $class; | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | # create local destructor for this class | 
| 411 |  |  |  |  |  |  | { | 
| 412 | 31 |  |  | 31 |  | 82114 | no strict 'refs'; | 
|  | 31 |  |  |  |  | 60 |  | 
|  | 31 |  |  |  |  | 3697 |  | 
|  | 152 |  |  |  |  | 334 |  | 
| 413 | 152 |  |  |  |  | 383 | my $local_method = $local_class . '::' . "DESTROY"; | 
| 414 |  |  |  |  |  |  | *$local_method = sub { | 
| 415 | 165 | 100 |  | 165 |  | 28714 | return if not $self->get_connected; | 
| 416 | 34 |  |  |  |  | 80 | my $oid_ref = shift; | 
| 417 |  |  |  |  |  |  | $self->send_request({ | 
| 418 |  |  |  |  |  |  | cmd => "client_destroy", | 
| 419 | 34 |  |  |  |  | 69 | oid => ${$oid_ref}, | 
|  | 34 |  |  |  |  | 181 |  | 
| 420 |  |  |  |  |  |  | }); | 
| 421 | 152 |  |  |  |  | 3305 | }; | 
| 422 |  |  |  |  |  |  | } | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | # create local methods for this class | 
| 425 | 152 |  |  |  |  | 482 | foreach my $method ( keys %{$methods} ) { | 
|  | 152 |  |  |  |  | 840 |  | 
| 426 | 1520 |  |  |  |  | 3742 | $local_method = $local_class . '::' . $method; | 
| 427 |  |  |  |  |  |  |  | 
| 428 | 1520 |  |  |  |  | 2601 | my $method_type = $methods->{$method}; | 
| 429 |  |  |  |  |  |  |  | 
| 430 | 1520 | 100 |  |  |  | 3531 | if ( $method_type eq '_constructor' ) { | 
|  |  | 100 |  |  |  |  |  | 
| 431 |  |  |  |  |  |  | # this is a constructor for this class | 
| 432 | 228 |  |  |  |  | 743 | my $request_method = $class . '::' . $method; | 
| 433 | 31 |  |  | 31 |  | 163 | no strict 'refs'; | 
|  | 31 |  |  |  |  | 75 |  | 
|  | 31 |  |  |  |  | 2709 |  | 
| 434 |  |  |  |  |  |  | *$local_method = sub { | 
| 435 | 40 |  |  | 40 |  | 3314 | shift; | 
| 436 | 40 |  |  |  |  | 505 | my $rc = $self->send_request({ | 
| 437 |  |  |  |  |  |  | cmd    => 'new', | 
| 438 |  |  |  |  |  |  | method => $request_method, | 
| 439 |  |  |  |  |  |  | params => \@_, | 
| 440 |  |  |  |  |  |  | }); | 
| 441 | 40 |  |  |  |  | 140 | my $oid = $rc->{oid}; | 
| 442 | 40 |  |  |  |  | 210 | return bless \$oid, $local_class; | 
| 443 | 228 |  |  |  |  | 2679 | }; | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  | elsif ( $method_type eq '1' ) { | 
| 446 |  |  |  |  |  |  | # this is a simple method | 
| 447 | 836 |  |  |  |  | 1380 | my $request_method = $method; | 
| 448 | 31 |  |  | 31 |  | 173 | no strict 'refs'; | 
|  | 31 |  |  |  |  | 54 |  | 
|  | 31 |  |  |  |  | 2961 |  | 
| 449 |  |  |  |  |  |  | *$local_method = sub { | 
| 450 | 249 |  |  | 249 |  | 45804 | my $oid_ref = shift; | 
| 451 |  |  |  |  |  |  | my $rc = $self->send_request({ | 
| 452 |  |  |  |  |  |  | cmd    => 'exec', | 
| 453 | 249 |  |  |  |  | 405 | oid    => ${$oid_ref}, | 
|  | 249 |  |  |  |  | 1725 |  | 
| 454 |  |  |  |  |  |  | method => $request_method, | 
| 455 |  |  |  |  |  |  | params => \@_, | 
| 456 |  |  |  |  |  |  | }); | 
| 457 | 248 | 50 |  |  |  | 989 | return unless $rc; | 
| 458 | 248 |  |  |  |  | 587 | $rc = $rc->{rc}; | 
| 459 | 248 | 100 |  |  |  | 517 | return @{$rc} if wantarray; | 
|  | 1 |  |  |  |  | 4 |  | 
| 460 | 247 |  |  |  |  | 2923 | return $rc->[0]; | 
| 461 | 836 |  |  |  |  | 7121 | }; | 
| 462 |  |  |  |  |  |  | } | 
| 463 |  |  |  |  |  |  | else { | 
| 464 |  |  |  |  |  |  | # this is a object returner | 
| 465 | 456 |  |  |  |  | 1840 | my $request_method = $method; | 
| 466 | 31 |  |  | 31 |  | 175 | no strict 'refs'; | 
|  | 31 |  |  |  |  | 57 |  | 
|  | 31 |  |  |  |  | 13688 |  | 
| 467 |  |  |  |  |  |  | *$local_method = sub { | 
| 468 | 71 |  |  | 71 |  | 494 | my $oid_ref = shift; | 
| 469 |  |  |  |  |  |  | my $rc      = $self->send_request({ | 
| 470 |  |  |  |  |  |  | cmd    => 'exec', | 
| 471 | 71 |  |  |  |  | 163 | oid    => ${$oid_ref}, | 
|  | 71 |  |  |  |  | 524 |  | 
| 472 |  |  |  |  |  |  | method => $request_method, | 
| 473 |  |  |  |  |  |  | params => \@_, | 
| 474 |  |  |  |  |  |  | }); | 
| 475 | 71 | 50 |  |  |  | 389 | return unless $rc; | 
| 476 | 71 |  |  |  |  | 230 | $rc = $rc->{rc}; | 
| 477 |  |  |  |  |  |  |  | 
| 478 | 71 |  |  |  |  | 127 | foreach my $val ( @{$rc} ) { | 
|  | 71 |  |  |  |  | 208 |  | 
| 479 | 72 | 100 |  |  |  | 382 | if ( ref $val eq 'ARRAY' ) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 480 | 1 |  |  |  |  | 2 | foreach my $list_elem ( @{$val} ) { | 
|  | 1 |  |  |  |  | 2 |  | 
| 481 | 10 |  |  |  |  | 17 | my ($class) = split( "=", "$list_elem", 2 ); | 
| 482 |  |  |  |  |  |  | $self->load_class($class) | 
| 483 | 10 | 50 |  |  |  | 16 | unless $loaded_classes->{$class}; | 
| 484 | 10 |  |  |  |  | 12 | my $list_elem_copy = $list_elem; | 
| 485 | 10 |  |  |  |  | 10 | $list_elem = \$list_elem_copy; | 
| 486 |  |  |  |  |  |  | bless $list_elem, | 
| 487 | 10 |  | 33 |  |  | 38 | ( $class_map->{$class} || $class ); | 
| 488 |  |  |  |  |  |  | } | 
| 489 |  |  |  |  |  |  | } | 
| 490 |  |  |  |  |  |  | elsif ( ref $val eq 'HASH' ) { | 
| 491 | 1 |  |  |  |  | 2 | foreach my $hash_elem ( values %{$val} ) { | 
|  | 1 |  |  |  |  | 9 |  | 
| 492 | 10 |  |  |  |  | 19 | my ($class) = split( "=", "$hash_elem", 2 ); | 
| 493 |  |  |  |  |  |  | $self->load_class($class) | 
| 494 | 10 | 50 |  |  |  | 14 | unless $loaded_classes->{$class}; | 
| 495 | 10 |  |  |  |  | 11 | my $hash_elem_copy = $hash_elem; | 
| 496 | 10 |  |  |  |  | 10 | $hash_elem = \$hash_elem_copy; | 
| 497 |  |  |  |  |  |  | bless $hash_elem, | 
| 498 | 10 |  | 33 |  |  | 28 | ( $class_map->{$class} || $class ); | 
| 499 |  |  |  |  |  |  | } | 
| 500 |  |  |  |  |  |  | } | 
| 501 |  |  |  |  |  |  | elsif ( defined $val ) { | 
| 502 | 69 |  |  |  |  | 378 | my ($class) = split( "=", "$val", 2 ); | 
| 503 |  |  |  |  |  |  | $self->load_class($class) | 
| 504 | 69 | 50 |  |  |  | 275 | unless $loaded_classes->{$class}; | 
| 505 | 69 |  |  |  |  | 147 | my $val_copy = $val; | 
| 506 | 69 |  |  |  |  | 161 | $val = \$val_copy; | 
| 507 | 69 |  | 33 |  |  | 1009 | bless $val, ( $class_map->{$class} || $class ); | 
| 508 |  |  |  |  |  |  | } | 
| 509 |  |  |  |  |  |  | } | 
| 510 | 71 | 100 |  |  |  | 222 | return @{$rc} if wantarray; | 
|  | 1 |  |  |  |  | 5 |  | 
| 511 | 70 |  |  |  |  | 302 | return $rc->[0]; | 
| 512 | 456 |  |  |  |  | 6110 | }; | 
| 513 |  |  |  |  |  |  | } | 
| 514 |  |  |  |  |  |  | } | 
| 515 |  |  |  |  |  |  |  | 
| 516 | 152 |  |  |  |  | 584 | return $local_class; | 
| 517 |  |  |  |  |  |  | } | 
| 518 |  |  |  |  |  |  |  | 
| 519 |  |  |  |  |  |  | sub send_request { | 
| 520 | 684 |  |  | 684 | 0 | 1484 | my $self = shift; | 
| 521 | 684 |  |  |  |  | 1283 | my ($request) = @_; | 
| 522 |  |  |  |  |  |  |  | 
| 523 | 684 |  |  |  |  | 1659 | my $message = $self->get_message_format->new( $self->get_sock ); | 
| 524 |  |  |  |  |  |  |  | 
| 525 | 684 |  |  |  |  | 3154 | $message->write_blocked($request); | 
| 526 |  |  |  |  |  |  |  | 
| 527 | 684 |  |  |  |  | 1094 | my $rc = eval { $message->read_blocked }; | 
|  | 684 |  |  |  |  | 2244 |  | 
| 528 |  |  |  |  |  |  |  | 
| 529 | 684 | 100 |  |  |  | 4599 | if ($@) { | 
| 530 | 7 |  |  |  |  | 175 | $self->error($@); | 
| 531 | 0 |  |  |  |  | 0 | return; | 
| 532 |  |  |  |  |  |  | } | 
| 533 |  |  |  |  |  |  |  | 
| 534 | 677 | 100 |  |  |  | 1668 | if ( not $rc->{ok} ) { | 
| 535 | 13 | 100 |  |  |  | 120 | $rc->{msg} .= "\n" if not $rc->{msg} =~ /\n$/; | 
| 536 | 13 |  |  |  |  | 3015 | croak ("$rc->{msg} -- called via Event::RPC::Client"); | 
| 537 |  |  |  |  |  |  | } | 
| 538 |  |  |  |  |  |  |  | 
| 539 | 664 |  |  |  |  | 3423 | return $rc; | 
| 540 |  |  |  |  |  |  | } | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | 1; | 
| 543 |  |  |  |  |  |  |  | 
| 544 |  |  |  |  |  |  | __END__ |