File Coverage

blib/lib/Net/DVBStreamer/Client.pm
Criterion Covered Total %
statement 12 63 19.0
branch 0 18 0.0
condition 0 7 0.0
subroutine 4 13 30.7
pod 6 6 100.0
total 22 107 20.5


line stmt bran cond sub pod time code
1             package Net::DVBStreamer::Client;
2              
3             ################
4             #
5             # DVBStreamer client module
6             #
7             # Nicholas J Humfrey
8             # njh@cpan.org
9             #
10              
11 1     1   23965 use strict;
  1         3  
  1         35  
12 1     1   5 use Carp;
  1         2  
  1         104  
13              
14 1     1   1079 use IO::Socket::INET;
  1         28215  
  1         8  
15              
16 1     1   778 use vars qw/$VERSION/;
  1         2  
  1         1042  
17             our $VERSION="0.01";
18             our $AUTOLOAD;
19              
20             my $BASE_PORT = 54197;
21             my $RESPONSE_PREFIX = 'DVBStreamer/';
22              
23              
24              
25             sub new {
26 0     0 1   my $class = shift;
27 0           my ($host, $adaptor) = @_;
28              
29             # Create self
30 0   0       my $self = {
      0        
31             'host' => $host || 'localhost',
32             'adaptor' => $adaptor || 0,
33             'server_version' => undef,
34             'errno' => 0,
35             'response' => '',
36             'sock' => undef,
37             };
38 0           bless $self, $class;
39              
40              
41             # Create INET Socket
42 0   0       $self->{'sock'} = new IO::Socket::INET(
43             PeerAddr => $self->{'host'},
44             PeerPort => $BASE_PORT + $self->{'adaptor'},
45             Proto => 'tcp') ||
46             croak( "Error: failed to connect to DVBStreamer server '$self->{'host'}'." );
47              
48              
49             # Read the response line and check it is a DVBStreamer server
50 0           my $line = $self->{'sock'}->getline();
51 0 0         croak "Error: remote server is not a DVBStreamer server.\n" if ($line !~ /^$RESPONSE_PREFIX/);
52            
53             # Parse the rest of the response line
54 0           my ($errno, $response) = $self->_parse_reponse_line( $line );
55 0 0         croak "Error: remote server is returned error number $errno: $response.\n" if ($errno != 0);
56 0 0         carp "Warning: remote server is not ready: $response.\n" if ($response ne 'Ready');
57            
58 0           return $self;
59             }
60              
61              
62             #
63             # Send a command a parse the response
64             #
65             sub send_command {
66 0     0 1   my $self = shift;
67 0           my ($command, @params) = @_;
68 0           my @result = ();
69            
70 0 0         croak "Usage: send_command( $command, [@params] )" unless (defined $command);
71              
72            
73             # Send the command
74 0           $self->{'sock'}->print( join(' ', $command, @params)."\n" );
75            
76             # Read the result line by line
77 0           while (my $line = $self->{'sock'}->getline()) {
78 0 0         if ($line =~ /^$RESPONSE_PREFIX/) {
79 0           my ($errno, $response) = $self->_parse_reponse_line( $line );
80 0 0         if ($errno != 0) {
    0          
    0          
81             # Error
82 0           return undef;
83             } elsif (scalar(@result)==1) {
84             # Success - return the single line as scalar
85 0           return $result[0];
86             } elsif (scalar(@result)) {
87             # Success - return the multiple lines as array
88 0           return @result;
89             } else {
90             # Success - return the response message
91 0           return $response;
92             }
93             } else {
94 0           chomp( $line );
95 0           push(@result, $line);
96             }
97             }
98              
99              
100             # Never saw a response line
101 0           $self->{'errno'} = -1;
102 0           $self->{'response'} = "Failed to read response from server";
103 0           return undef;
104             }
105              
106             #
107             # Return the version number of the remote server
108             #
109             sub server_version {
110 0     0 1   my $self = shift;
111 0           return $self->{'server_version'};
112             }
113              
114             #
115             # Returns the error number from the last command sent
116             #
117             sub errno {
118 0     0 1   my $self = shift;
119 0           return $self->{'errno'};
120             }
121              
122             #
123             # Returns the response message from the last command sent
124             #
125             sub response {
126 0     0 1   my $self = shift;
127 0           return $self->{'response'};
128             }
129              
130              
131             #
132             # Authenticate with the remote server
133             #
134             sub authenticate {
135 0     0 1   my $self = shift;
136 0           return $self->send_command( 'auth', @_ );
137             }
138              
139              
140              
141              
142             #
143             # Internal method to parse a server response message
144             #
145             sub _parse_reponse_line {
146 0     0     my $self = shift;
147 0           my ($line) = @_;
148            
149 0           my ($version, $errno, $response) = ($line =~ /^$RESPONSE_PREFIX([\d\.]+)\/(\d+)\s(.*)\n$/);
150 0           $self->{'server_version'} = $version;
151 0           $self->{'errno'} = $errno;
152 0           $self->{'response'} = $response;
153            
154 0           return ($errno, $response);
155             }
156              
157              
158             #
159             # Pass unhandled method calls on to send_command()
160             #
161             sub AUTOLOAD {
162 0     0     my $self = shift;
163            
164 0           my $cmd = substr($AUTOLOAD, rindex($AUTOLOAD, '::')+2);
165 0           return $self->send_command( $cmd, @_ );
166             }
167              
168              
169             #
170             # Close the socket before the object is destroyed
171             #
172             sub DESTROY {
173 0     0     my $self=shift;
174            
175 0 0         if (defined $self->{'sock'}) {
176 0           $self->{'sock'}->close();
177 0           undef $self->{'sock'};
178             }
179             }
180              
181              
182             1;
183              
184             __END__