File Coverage

blib/lib/Net/RTP.pm
Criterion Covered Total %
statement 56 86 65.1
branch 12 40 30.0
condition 5 16 31.2
subroutine 14 16 87.5
pod 4 5 80.0
total 91 163 55.8


line stmt bran cond sub pod time code
1             package Net::RTP;
2              
3             ################
4             #
5             # Net::RTP: Pure Perl Real-time Transport Protocol (RFC3550)
6             #
7             # Nicholas J Humfrey
8             # njh@cpan.org
9             #
10              
11 2     2   30917 use Net::RTP::Packet;
  2         7  
  2         66  
12 2     2   2780 use Socket;
  2         10480  
  2         1359  
13 2     2   35 use strict;
  2         5  
  2         70  
14 2     2   17 use Carp;
  2         4  
  2         2483  
15              
16              
17              
18             # Use whatever Superclass we can find first
19             # we would prefer to have a multicast socket...
20             BEGIN {
21 2     2   8 my @superclasses = (
22             'IO::Socket::Multicast6 0.02',
23             'IO::Socket::Multicast 1.00',
24             'IO::Socket::INET6 2.51',
25             'IO::Socket::INET 1.20',
26             );
27            
28 2         4 our $SUPER_CLASS = undef;
29 2         6 foreach my $super (@superclasses) {
30 4     2   336 eval "use $super";
  2     2   1638  
  0         0  
  0         0  
  2         2068  
  2         73522  
  2         14  
31 4 100       2851 unless ($@) {
32 2         158 ($SUPER_CLASS) = ($super =~ /^([\w:]+)/);
33 2         7 last;
34             }
35             }
36            
37 2 50       11 unless (defined $SUPER_CLASS) {
38 0         0 die "Failed to load any of super classes.";
39             }
40            
41            
42             # Check to see if Socket6 is available
43 2         6 our $HAVE_SOCKET6 = 0;
44 2     2   162 eval "use Socket6 qw/ AF_INET6 unpack_sockaddr_in6 inet_ntop /;";
  2         2157  
  2         2907  
  2         1171  
45 2 50       84 $HAVE_SOCKET6=1 unless ($@);
46             }
47              
48              
49              
50 2     2   16 use vars qw/$VERSION @ISA $SUPER_CLASS $HAVE_SOCKET6/;
  2         3  
  2         1960  
51             @ISA = ($SUPER_CLASS);
52             $VERSION="0.09";
53              
54              
55              
56              
57             sub new {
58 2     2 1 112 my $class = shift;
59 2 100       13 unshift @_,(Proto => 'udp') unless @_;
60 2         30 return $class->SUPER::new(@_);
61             }
62              
63              
64             sub configure {
65 2     2 0 339 my($self,$arg) = @_;
66            
67             # Default to UDP instead of TCP
68 2   100     15 $arg->{Proto} ||= 'udp';
69 2   50     19 $arg->{ReuseAddr} ||= 1;
70 2         20 my $result = $self->SUPER::configure($arg);
71              
72            
73 2 50       555 if (defined $result) {
74             # Join group if it a multicast IP address
75 2         21 my $group = $self->sockhost();
76 2 50       133 if (_is_multicast_ip($group)) {
77 0 0       0 if ($self->superclass() =~ /Multicast/) {
78             #print "Joining group: $group\n";
79 0 0       0 $self->mcast_add( $group ) || croak "Failed to join multicast group";
80             } else {
81 0         0 croak "Error: can't receive multicast without either ".
82             "IO::Socket::Multicast or IO::Socket::Multicast6 installed.";
83             }
84             }
85             }
86            
87 2         8 return $result;
88             }
89              
90              
91             sub _is_multicast_ip {
92 2     2   10 my ($group) = @_;
93            
94 2 50       11 return 0 unless (defined $group);
95            
96             # IPv4 multicast address ?
97 2 50       27 if ($group =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
    0          
98 2 50 33     15 return 1 if ($1 >= 224 and $1 <= 239);
99            
100             # IPv6 multicast address ?
101             } elsif ($group =~ /^ff[0-9a-f]{2}\:/i) {
102 0         0 return 1;
103             }
104              
105             # Not an multicast IP
106 2         8 return 0;
107             }
108              
109              
110             sub superclass {
111 0     0 1 0 return $SUPER_CLASS;
112             }
113              
114              
115             sub recv {
116 0     0 1 0 my $self=shift;
117 0         0 my ($size) = @_;
118            
119             # Default read size
120 0 0       0 $size = 2048 unless (defined $size);
121            
122             # Receive a binary packet
123 0         0 my $data = undef;
124 0         0 my $sockaddr_in = $self->SUPER::recv($data, $size);
125 0 0 0     0 if (defined $data and $data ne '') {
126            
127             # Parse the packet
128 0         0 my $packet = new Net::RTP::Packet( $data );
129            
130             # Store the source address
131 0 0 0     0 if ($sockaddr_in ne '' and defined $packet)
132             {
133 0 0       0 if ($self->sockdomain() == &AF_INET) {
    0          
134 0         0 my ($port,$addr) = unpack_sockaddr_in($sockaddr_in);
135 0         0 $packet->{'source_ip'} = inet_ntoa($addr);
136 0         0 $packet->{'source_port'} = $port;
137            
138             } elsif ($HAVE_SOCKET6) {
139 0         0 eval {
140 0 0       0 if ($self->sockdomain() == &AF_INET6) {
141 0         0 my ($port,$addr) = unpack_sockaddr_in6($sockaddr_in);
142 0         0 $packet->{'source_ip'} = inet_ntop(&AF_INET6, $addr);
143 0         0 $packet->{'source_port'} = $port;
144             }
145             };
146             }
147            
148             # Failed to decode socket address ?
149 0 0       0 unless (defined $packet->{'source_ip'}) {
150 0         0 warn "Failed to get socket address for family: ".$self->sockdomain();
151             }
152             }
153            
154 0         0 return $packet;
155             }
156            
157 0         0 return undef;
158             }
159              
160              
161             sub send {
162 1     1 1 86 my $self=shift;
163 1         3 my ($packet) = @_;
164            
165 1 50 33     10 if (!defined $packet or ref($packet) ne 'Net::RTP::Packet') {
166 0         0 croak "Net::RTP->send() takes a Net::RTP::Packet as its only argument";
167             }
168            
169             # Build packet and send it
170 1         6 my $data = $packet->encode();
171 1         13 return $self->SUPER::send($data);
172             }
173              
174              
175             sub DESTROY {
176 2     2   572 my $self=shift;
177 2         34 return $self->SUPER::DESTROY(@_);
178             }
179              
180              
181              
182             1;
183              
184             __END__