File Coverage

blib/lib/Net/SIP/Simple/Call.pm
Criterion Covered Total %
statement 266 352 75.5
branch 90 146 61.6
condition 58 121 47.9
subroutine 26 31 83.8
pod 12 12 100.0
total 452 662 68.2


line stmt bran cond sub pod time code
1              
2             ###########################################################################
3             # Net::SIP::Simple::Call
4             # manages a call, contains Net::SIP::Endpoint::Context
5             # has hooks for some RTP handling
6             ###########################################################################
7              
8 41     41   311 use strict;
  41         91  
  41         1326  
9 41     41   240 use warnings;
  41         90  
  41         1639  
10              
11             package Net::SIP::Simple::Call;
12 41     41   236 use base 'Net::SIP::Simple';
  41         96  
  41         8160  
13 41     41   433 use fields qw( call_cleanup rtp_cleanup ctx param );
  41         139  
  41         325  
14              
15             ###########################################################################
16             # call_cleanup: callbacks for cleaning up call, called at the end
17             # rtp_cleanup: callbacks for cleaning up RTP connections, called
18             # on reINVITEs and at the end
19             # ctx: Net::SIP::Endpoint::Context object for this call
20             # param: various parameter to control behavior
21             # leg: thru which leg the call should be directed (default: first leg)
22             # init_media: initialize handling for media (RTP) data, see
23             # Net::SIP::Simple::RTP
24             # sdp : predefined Net::SIP::SDP or data accepted from NET::SIP::SDP->new
25             # media_lsocks: if sdp is provided the sockets has to be provided too
26             # \@list of sockets for each media, each element in the list is
27             # either the socket (udp) or [ rtp_socket,rtpc_socket ]
28             # sdp_on_ack: send SDP data on ACK, not on INVITE
29             # asymetric_rtp: socket for sending media to peer are not the same as
30             # the sockets, where the media gets received, creates media_ssocks
31             # media_ssocks: sockets used to send media to peer. If not given
32             # and asymetric_rtp is used the sockets will be created, if not given
33             # and not !asymetric_rtp media_lsocks will be used, e.g. symetric RTP
34             # recv_bye: callback or scalar-ref used when call is closed by peer
35             # send_bye: callback or scalar-ref used when call is closed by local side
36             # sdp_peer: Net::SIP::SDP from peer
37             # clear_sdp: ' causes that keys sdp,sdp_peer,media_ssocks and
38             # media_lsocks gets cleared on new invite, so that a new SDP session
39             # need to be established
40             # cb_final: callback which will be called on final response in INVITE
41             # with (status,self,%args) where status is OK|FAIL
42             # cb_preliminary: callback which will be called on preliminary response
43             # in INVITE with (self,code,packet)
44             # cb_established: callback which will be called on receiving ACK in INVITE
45             # with (status,self) where status is OK|FAIL
46             # cb_invite: callback called with ($self,$packet) when INVITE is received
47             # cb_dtmf: callback called with ($event,$duration) when DTMF events
48             # are received, works only with media handling from Net::SIP::Simple::RTP
49             # cb_notify: callback called with ($self,$packet) when NOTIFY is received
50             # sip_header: hashref of SIP headers to add
51             # call_on_hold: one-shot parameter to set local media addr to 0.0.0.0,
52             # will be set to false after use
53             # dtmf_methods: supported DTMF methods for receiving, default 'rfc2833,audio'
54             # rtp_param: [ pt,size,interval,name ] RTP payload type, packet size and interval
55             # between packets managed in Net::SIP::Simple::RTP, default is PCMU/8000,
56             # e.g [ 0,160,160/8000 ]
57             # a name can be added in which case an rtpmap and ptme entry will be created in the
58             # SDP, e.g. [ 97,50,0.03,'iLBC/8000' ]
59             ###########################################################################
60              
61 41     41   4227 use Net::SIP::Util qw(:all);
  41         89  
  41         8167  
62 41     41   320 use Net::SIP::Debug;
  41         86  
  41         337  
63 41     41   354 use Net::SIP::DTMF 'dtmf_extractor';
  41         110  
  41         2533  
64 41     41   290 use Socket;
  41         95  
  41         20356  
65 41     41   306 use Storable 'dclone';
  41         86  
  41         2647  
66 41     41   271 use Carp 'croak';
  41         89  
  41         1937  
67 41     41   276 use Scalar::Util 'weaken';
  41         81  
  41         167045  
68              
69             ###########################################################################
70             # create a new call based on a controller
71             # Args: ($class,$control,$ctx;$param)
72             # $control: Net::SIP::Simple object which controls this call
73             # $ctx: SIP address of peer for new call or NET::SIP::Endpoint::Context
74             # or hashref for constructing NET::SIP::Endpoint::Context
75             # $param: see description of field 'param'
76             # Returns: $self
77             ###########################################################################
78             sub new {
79 51     51 1 328 my ($class,$control,$ctx,$param) = @_;
80 51         203 my $self = fields::new( $class );
81 51         12860 %$self = %$control;
82              
83 51         197 $self->{ua_cleanup} = [];
84 51 100       489 $ctx = { to => $ctx } if ! ref($ctx);
85 51   66     769 $ctx->{from} ||= $self->{from};
86 51   33     509 $ctx->{contact} ||= $self->{contact};
87 51   66     357 $ctx->{auth} ||= $self->{auth};
88 51   33     272 $ctx->{route} ||= $self->{route};
89 51         112 $self->{ctx} = $ctx;
90              
91 51         129 $self->{call_cleanup} = [];
92 51         131 $self->{rtp_cleanup} = [];
93 51   100     349 $self->{param} = $param ||= {};
94 51   66     1322 $param->{init_media} ||= $self->rtp( 'media_recv_echo' );
95 51   50     716 $param->{rtp_param} ||= [ 0,160,160/8000 ]; # PCMU/8000: 50*160 bytes/second
96 51   50     545 $param->{dtmf_events} ||= []; # get added by sub dtmf
97              
98 51 100       212 if (my $cb = delete $param->{cb_cleanup}) {
99 13         64 push @{$self->{call_cleanup}}, $cb;
  13         76  
100             }
101 51         192 return $self;
102             }
103              
104             ###########################################################################
105             # Cleanups
106             # explicit cleanups might be necessary if callbacks reference back into
107             # the object so that it cannot be cleaned up by simple ref-counting alone
108             ###########################################################################
109              
110             sub cleanup {
111 43     43 1 120 my Net::SIP::Simple::Call $self = shift;
112 43         320 $self->rtp_cleanup;
113 43         92 while ( my $cb = shift @{ $self->{call_cleanup} } ) {
  56         6959  
114 13         86 invoke_callback($cb,$self)
115             }
116 43 50       206 if (my $ctx = delete $self->{ctx}) {
117 43         275 $self->{endpoint}->close_context( $ctx );
118             }
119 43         195 $self->{param} = {};
120             }
121              
122             sub rtp_cleanup {
123 87     87 1 221 my Net::SIP::Simple::Call $self = shift;
124 87         192 while ( my $cb = shift @{ $self->{rtp_cleanup} } ) {
  175         1569  
125 88         301 invoke_callback($cb,$self)
126             }
127 87         360 DEBUG( 100,"done" );
128             }
129              
130             sub DESTROY {
131 50     50   2356 DEBUG( 100,"done" );
132             }
133              
134              
135             ###########################################################################
136             # return peer of call
137             # Args: $self
138             # Returns: $peer
139             ###########################################################################
140             sub get_peer {
141 0     0 1 0 my Net::SIP::Simple::Call $self = shift;
142 0         0 return $self->{ctx}->peer;
143             }
144              
145             ###########################################################################
146             # set parameter
147             # Args: ($self,%param)
148             # Returns: $self
149             ###########################################################################
150             sub set_param {
151 2     2 1 5 my Net::SIP::Simple::Call $self = shift;
152 2         10 my %args = @_;
153 2         9 @{ $self->{param} }{ keys %args } = values %args;
  2         49  
154 2         7 return $self;
155             }
156              
157             ###########################################################################
158             # get value for parameter(s)
159             # Args: ($self,@keys)
160             # Returns: @values|$value[0]
161             ###########################################################################
162             sub get_param {
163 0     0 1 0 my Net::SIP::Simple::Call $self = shift;
164 0         0 my @v = @{$self->{param}}{@_};
  0         0  
165 0 0       0 return wantarray ? @v : $v[0];
166             }
167              
168             ###########################################################################
169             # (Re-)Invite other party
170             # Args: ($self,%param)
171             # %param: see description of field 'param', gets merged with param
172             # already on object so that the values are valid for future use
173             # Returns: Net::SIP::Endpoint::Context
174             # Comment:
175             # If cb_final callback was not given it will loop until it got a final
176             # response, otherwise it will return immediately
177             ###########################################################################
178             sub reinvite {
179 36     36 1 1000472 my Net::SIP::Simple::Call $self = shift;
180 36         166 my %args = @_;
181              
182 36         155 my $param = $self->{param};
183 36         115 my $clear_sdp = delete $args{clear_sdp};
184 36 100       225 $clear_sdp = $param->{clear_sdp} if ! defined $clear_sdp;
185 36 100       151 if ( $clear_sdp ) {
186             # clear SDP keys so that a new SDP session will be created
187 2         5 @{ $param }{qw( sdp _sdp_saved sdp_peer media_ssocks media_lsocks )} = ()
  2         54  
188             }
189 36 100       581 $self->{param} = $param = { %$param, %args } if %args;
190              
191              
192 36         173 my $leg = $param->{leg};
193 36 100       146 if ( ! $leg ) {
194 35         369 ($leg) = $self->{dispatcher}->get_legs();
195 35         108 $param->{leg} = $leg;
196             }
197              
198 36         116 my $ctx = $self->{ctx};
199              
200 36         85 my $sdp;
201 36 50       130 if ( ! $param->{sdp_on_ack} ) {
202 36         700 $self->_setup_local_rtp_socks;
203             $sdp = $param->{sdp}
204 36         118 }
205              
206             # predefined callback
207             my $cb = sub {
208 105   50 105   369 my Net::SIP::Simple::Call $self = shift || return;
209 105         385 my ($endpoint,$ctx,$errno,$code,$packet,$leg,$from,$ack) = @_;
210              
211 105 100       282 if ( $errno ) {
212 7 100 66     118 if (!$code || $code != 487) {
213 1 50       21 $self->error( "Failed with error $errno".( $code ? " code=$code" :"" ) );
214             } else {
215             # code 487: request was canceled, probably be me -> ignore
216             }
217 7         45 invoke_callback( $param->{cb_final}, 'FAIL',$self,errno => $errno,
218             code => $code,packet => $packet );
219 7         242 return;
220             }
221              
222             # new requests in existing call are handled in receive()
223 98 100       390 return $self->receive( @_ ) if $packet->is_request;
224              
225             # response to INVITE
226             # all other responses will not be propagated to this callback
227 94         285 my $param = $self->{param};
228 94 100       590 if ( $code =~m{^1\d\d} ) {
    50          
229             # preliminary response, ignore
230 66         297 DEBUG(10,"got preliminary response of %s|%s to INVITE",$code,$packet->msg );
231 66         395 invoke_callback( $param->{cb_preliminary},$self,$code,$packet );
232 66         5027 return;
233             } elsif ( $code !~m{^2\d\d} ) {
234 0         0 DEBUG(10,"got response of %s|%s to INVITE",$code,$packet->msg );
235 0         0 invoke_callback( $param->{cb_final},'FAIL',$self,code => $code,
236             packet => $packet );
237 0         0 return;
238             }
239              
240             # cleanup RTP from last call
241 28         267 $self->rtp_cleanup;
242              
243 28 50       235 $self->_setup_peer_rtp_socks( $packet ) || do {
244 0         0 invoke_callback( $param->{cb_final},'FAIL',$self );
245 0         0 return;
246             };
247 28 50 33     163 if ( $param->{sdp_on_ack} && $ack ) {
248 0         0 $self->_setup_local_rtp_socks;
249 0         0 $ack->set_body( $param->{sdp} );
250             }
251 28         172 invoke_callback( $param->{cb_final},'OK',$self, packet => $packet );
252 28         103 invoke_callback( $param->{init_media},$self,$param );
253 36         896 };
254              
255              
256 36         150 my $stopvar = 0;
257 36   100     699 $param->{cb_final} ||= \$stopvar;
258 36         105 $cb = [ $cb,$self ];
259 36         163 weaken( $cb->[1] );
260             $self->{ctx} = $self->{endpoint}->invite(
261             $ctx, $cb, $sdp,
262 36 50       514 $param->{sip_header} ? %{ $param->{sip_header} } : ()
  0         0  
263             );
264              
265 36 100       202 if ( $param->{cb_final} == \$stopvar ) {
266              
267             # This callback will be called on timeout or response to cancel which
268             # got send after ring_time was over
269 27         58 my $noanswercb;
270 27 50       96 if ( $param->{ring_time} ) {
271             $noanswercb = sub {
272 0   0 0   0 my Net::SIP::Simple::Call $self = shift || return;
273 0         0 my ($endpoint,$ctx,$errno,$code,$packet,$leg,$from,$ack) = @_;
274              
275 0         0 $stopvar = 'NOANSWER' ;
276 0         0 my $param = $self->{param};
277 0         0 invoke_callback( $param->{cb_noanswer}, 'NOANSWER',$self,
278             errno => $errno,code => $code,packet => $packet );
279              
280 0 0       0 if ( $code =~ m{^2\d\d} ) {
281 0         0 DEBUG(10,"got response of %s|%s to CANCEL",$code,$packet->msg );
282 0         0 invoke_callback( $param->{cb_final},'NOANSWER',$self,code => $code,
283             packet => $packet );
284             }
285 0         0 };
286 0         0 $noanswercb = [ $noanswercb,$self ];
287 0         0 weaken( $noanswercb->[1] );
288              
289             # wait until final response
290 0         0 $self->loop( $param->{ring_time}, \$stopvar );
291              
292 0 0       0 unless ($stopvar) { # timed out
293 0         0 $self->{endpoint}->cancel_invite( $self->{ctx},undef, $noanswercb );
294 0         0 $self->loop( \$stopvar );
295             }
296             } else {
297             # wait until final response
298 27         340 $self->loop( \$stopvar );
299             }
300              
301 27         263 $param->{cb_final} = undef;
302             }
303 36         540 return $self->{ctx};
304             }
305              
306              
307             ###########################################################################
308             # cancel call
309             # Args: ($self,%args)
310             # %args:
311             # cb_final: callback when CANCEL was delivered. If not given send_cancel
312             # callback on Call object will be used
313             # Returns: true if call could be canceled
314             # Comment: cb_final gets triggered if the reply for the CANCEL is received
315             # or waiting for the reply timed out
316             ###########################################################################
317             sub cancel {
318 6     6 1 3495 my Net::SIP::Simple::Call $self = shift;
319 6         18 my %args = @_;
320              
321 6         20 my $cb = delete $args{cb_final};
322 6         15 %args = ( %{ $self->{param} }, %args );
  6         89  
323 6   33     135 $cb ||= $args{send_cancel};
324              
325             my $cancel_cb = [
326             sub {
327 6   50 6   21 my Net::SIP::Simple::Call $self = shift || return;
328 6         19 my ($cb,$args,$endpoint,$ctx,$error,$code) = @_;
329             # we don't care about the cause of this callback
330             # it might be a successful or failed reply packet or no reply
331             # packet at all (timeout) - the call is considered closed
332             # in any case except for 1xx responses
333 6 50 33     117 if ( $code && $code =~m{^1\d\d} ) {
334 0         0 DEBUG( 10,"got prelimary response for CANCEL" );
335 0         0 return;
336             }
337 6         28 invoke_callback( $cb,$args );
338             },
339 6         98 $self,$cb,\%args
340             ];
341 6         41 weaken( $cancel_cb->[1] );
342              
343 6         49 return $self->{endpoint}->cancel_invite( $self->{ctx}, undef, $cancel_cb );
344             }
345              
346             ###########################################################################
347             # end call
348             # Args: ($self,%args)
349             # %args:
350             # cb_final: callback when BYE was delivered. If not given send_bye
351             # callback on Call object will be used
352             # Returns: NONE
353             # Comment: cb_final gets triggered if the reply for the BYE is received
354             # or waiting for the reply timed out
355             ###########################################################################
356             sub bye {
357 27     27 1 1000662 my Net::SIP::Simple::Call $self = shift;
358 27         203 my %args = @_;
359              
360 27         125 my $cb = delete $args{cb_final};
361 27         75 %args = ( %{ $self->{param} }, %args );
  27         696  
362 27   33     211 $cb ||= $args{send_bye};
363              
364             my $bye_cb = [
365             sub {
366 27   50 27   129 my Net::SIP::Simple::Call $self = shift || return;
367 27         91 my ($cb,$args,$endpoint,$ctx,$error,$code) = @_;
368             # we don't care about the cause of this callback
369             # it might be a successful or failed reply packet or no reply
370             # packet at all (timeout) - the call is considered closed
371             # in any case except for 1xx responses
372             # FIXME: should we check for 302 moved etc?
373 27 50 33     426 if ( $code && $code =~m{^1\d\d} ) {
374 0         0 DEBUG( 10,"got prelimary response for BYE" );
375 0         0 return;
376             }
377 27         212 invoke_callback( $cb,$args );
378 27         153 $self->cleanup;
379             },
380 27         880 $self,$cb,\%args
381             ];
382 27         246 weaken( $bye_cb->[1] );
383              
384 27         379 $self->{endpoint}->new_request( 'BYE',$self->{ctx}, $bye_cb );
385             }
386              
387             ###########################################################################
388             # request
389             # Args: ($self,$method,$body,%args)
390             # $method: method name
391             # $body: optional body
392             # %args:
393             # cb_final: callback when response got received
394             # all other args will be used to create request (mostly as header
395             # for the request, see Net::SIP::Endpoint::new_request)
396             # Returns: NONE
397             ###########################################################################
398             sub request {
399 0     0 1 0 my Net::SIP::Simple::Call $self = shift;
400 0         0 my ($method,$body,%args) = @_;
401              
402 0         0 my $cb = delete $args{cb_final};
403 0         0 my %cbargs = ( %{ $self->{param} }, %args );
  0         0  
404              
405             my $rqcb = [
406             sub {
407 0   0 0   0 my Net::SIP::Simple::Call $self = shift || return;
408 0         0 my ($cb,$args,$endpoint,$ctx,$error,$code,$pkt) = @_;
409 0 0 0     0 if ( $code && $code =~m{^1\d\d} ) {
410 0         0 DEBUG( 10,"got prelimary response for request $method" );
411 0         0 return;
412             }
413 0 0       0 invoke_callback( $cb,
414             $error ? 'FAIL':'OK',
415             $self,
416             { code => $code, packet => $pkt}
417             );
418             },
419 0         0 $self,$cb,\%cbargs
420             ];
421 0         0 weaken( $rqcb->[1] );
422              
423 0         0 $self->{endpoint}->new_request( $method,$self->{ctx},$rqcb,$body,%args );
424             }
425              
426             ###########################################################################
427             # send DTMF (dial tone) events
428             # Args: ($self,$events,%args)
429             # $events: string of characters from dial pad, any other character will
430             # cause pause
431             # %args:
432             # duration: length of dial tone in milliseconds, default 100
433             # cb_final: callback called with (status,errormsg) when done
434             # status can be OK|FAIL. If not given will wait until all
435             # events are sent
436             # methods: methods it should try for DTMF in this order
437             # default is 'rfc2833,audio'. If none of the specified
438             # methods is supported by peer it will croak
439             # Returns: NONE
440             # Comments: works only with media handling from Net::SIP::Simple::RTP
441             ###########################################################################
442             sub dtmf {
443 12     12 1 155 my ($self,$events,%args) = @_;
444 12   50     71 my $duration = $args{duration} || 100;
445 12   50     143 my @methods = split(m{[\s,]+}, lc($args{methods}||'rfc2833,audio'));
446              
447 12         34 my %payload_type;
448 12   66     152 while ( ! %payload_type
449             and my $m = shift(@methods)) {
450 12         26 my $type;
451 12 100       89 if ( $m eq 'rfc2833' ) {
    50          
452             $type = $self->{param}{sdp_peer}
453 6   33     107 && $self->{param}{sdp_peer}->name2int('telephone-event/8000','audio');
454             } elsif ( $m eq 'audio' ) {
455             $type = $self->{param}{sdp_peer}
456 6   50     96 && $self->{param}{sdp_peer}->name2int('PCMU/8000','audio')
457             || 0; # default id for PCMU/8000
458             } else {
459 0         0 croak("unknown method $m in methods:$args{methods}");
460             }
461 12 50       119 %payload_type = ( $m."_type" => $type ) if defined $type;
462             }
463 12 50       38 %payload_type or croak("no usable DTMF method found");
464              
465 12         41 my $arr = $self->{param}{dtmf_events};
466 12         16 my $lastev;
467 12         67 for( split('',$events)) {
468 48 50       185 if ( m{[\dA-D*#]} ) {
469 48 100       107 if (defined $lastev) {
470             # force some silence to distinguish DTMF
471 36 50       137 push @$arr, {
472             duration => ($lastev eq $_) ? 100 : 50,
473             %payload_type
474             }
475             }
476 48         265 push @$arr, {
477             event => $_,
478             duration => $duration,
479             %payload_type,
480             };
481 48         119 $lastev = $_;
482             } else {
483             # pause
484 0         0 push @$arr, { duration => $duration, %payload_type };
485 0         0 $lastev = undef;
486             }
487             }
488 12 50       44 if ( my $cb_final = $args{cb_final} ) {
489 0         0 push @$arr, { cb_final => $cb_final }
490             } else {
491 12         34 my $stopvar;
492 12         55 push @$arr, { cb_final => \$stopvar };
493 12         84 $self->loop(\$stopvar);
494             }
495             }
496              
497             ###########################################################################
498             # handle new packets within existing call
499             # Args: ($self,$endpoint,$ctx,$error,$code,$packet,$leg,$from)
500             # $endpoint: the endpoint
501             # $ctx: context for call
502             # $error: errno if error occurred
503             # $code: code from responses
504             # $packet: incoming packet
505             # $leg: leg where packet came in
506             # $from: addr from where packet came
507             # Returns: NONE
508             ###########################################################################
509             sub receive {
510 48     48 1 353 my ($self,$endpoint,$ctx,$error,$code,$packet,$leg,$from) = @_;
511 48 50       319 if ( ! $packet ) {
    50          
512 0         0 $self->error( "error occurred: $error" );
513             } elsif ( $packet->is_request ) {
514 48         192 my $method = $packet->method;
515 48         162 my $param = $self->{param};
516              
517 48 100 100     627 if ( $method eq 'BYE' || $method eq 'CANCEL' ) {
    50 66        
    0          
    0          
518             # tear down
519 16         368 $self->cleanup;
520 16         135 invoke_callback( $param->{recv_bye},$param);
521             # everything else already handled by Net::SIP::Endpoint::Context
522              
523             } elsif ( $method eq 'ACK' || $method eq 'INVITE' ) {
524              
525             # can transport sdp data
526 32 100       97 if ( my $sdp_peer = eval { $packet->sdp_body } ) {
  32 50       295  
527 16         114 DEBUG( 50,"got sdp data from peer: ".$sdp_peer->as_string );
528 16         206 $self->_setup_peer_rtp_socks( $sdp_peer );
529             } elsif ($@) {
530             # mailformed SDP?
531 0         0 DEBUG(10,"SDP parsing failed, ignoring packet: $@");
532 0         0 return;
533             }
534              
535 32 100       214 if ( $method eq 'INVITE' ) {
    50          
536              
537 16 50       119 if ( $param->{clear_sdp} ) {
538             # clear SDP keys so that a new SDP session will be created
539 0         0 @{ $param }{qw( sdp _sdp_saved sdp_peer media_ssocks media_lsocks )} = ()
  0         0  
540             }
541              
542 16   66     244 $param->{leg} ||= $leg;
543 16         196 $self->_setup_local_rtp_socks;
544 16         129 my $resp = invoke_callback($param->{cb_invite},$self,$packet);
545              
546             # by default send 200 OK with sdp body
547             $resp = $packet->create_response('200','OK',{},$param->{sdp})
548 16 50 33     252 if ! $resp || ! UNIVERSAL::isa($resp,'Net::SIP::Packet');
549 16         131 DEBUG( 100,'created response '.$resp->as_string );
550 16         156 $self->{endpoint}->new_response( $ctx,$resp,$leg,$from );
551              
552             } elsif ( $method eq 'ACK' ) {
553 16         126 $self->rtp_cleanup; # close last RTP session
554 16         190 invoke_callback($param->{cb_established},'OK',$self);
555 16         8307 invoke_callback($param->{init_media},$self,$param);
556             }
557              
558             } elsif ( $method eq 'OPTIONS' ) {
559              
560 0         0 my $response = $packet->create_response( '200','OK',$self->{options} );
561 0         0 $self->{endpoint}->new_response( $ctx,$response,$leg,$from );
562              
563             } elsif ( $method eq 'NOTIFY' ) {
564              
565 0         0 my $response = $packet->create_response( '200','OK' );
566 0         0 $self->{endpoint}->new_response( $ctx,$response,$leg,$from );
567 0         0 invoke_callback($param->{cb_notify},$self,$packet);
568             }
569              
570             } else {
571             # don't expect any responses.
572             # Response to BYE is handled by Net::SIP::Endpoint::Context
573             # other responses from the peer I don't expect
574 0         0 DEBUG( 100,"got response. WHY? DROP." );
575             }
576             }
577              
578             ###########################################################################
579             # setup $self->{param} for remote socks from remote SDP data
580             # Args: ($self,$data)
581             # $data: packet containing sdp_body (Net::SIP::Packet) or
582             # SDP data (Net::SIP::SDP)
583             # Returns: NONE
584             ###########################################################################
585             sub _setup_peer_rtp_socks {
586 44     44   123 my Net::SIP::Simple::Call $self = shift;
587 44         141 my $param = $self->{param};
588 44   33     153 my $data = shift || $param->{sdp_peer};
589              
590 44         94 my $sdp_peer;
591 44 100       381 if ( UNIVERSAL::isa( $data, 'Net::SIP::Packet' )) {
592 28 50       284 $sdp_peer = $data->sdp_body or do {
593 0         0 $self->error( "No SDP body in packet" );
594 0         0 return;
595             };
596             } else {
597 16         61 $sdp_peer = $data
598             }
599              
600 44         396 $param->{sdp_peer} = $sdp_peer;
601              
602 44         532 my @media = $sdp_peer->get_media;
603 44         182 my $ls = $param->{media_lsocks};
604 44 50 66     847 if ( $ls && @$ls && @media != @$ls ) {
      66        
605 0         0 $self->error( "Unexpected number of media entries in SDP from peer" );
606 0         0 return;
607             }
608              
609 44         353 my $raddr = $param->{media_raddr} = [];
610 44         121 my @media_dtmfxtract;
611 44         412 for( my $i=0;$i<@media;$i++) {
612 44         107 my $m = $media[$i];
613 44   50     168 my $range = $m->{range} || 1;
614 44         588 my $paddr = ip_canonical($m->{addr});
615 44 100 66     986 if (!$m->{port} or $paddr eq '0.0.0.0' or $paddr eq '::') {
      66        
616             # on-hold for this media
617 1         7 push @$raddr, undef;
618             } else {
619 43         205 my @socks = map { ip_parts2sockaddr($m->{addr},$m->{port}+$_) }
  86         428  
620             (0..$range-1);
621 43 50       242 push @$raddr, @socks == 1 ? $socks[0] : \@socks;
622              
623 43 100 66     673 if ( $m->{media} eq 'audio' and $param->{cb_dtmf} ) {
624 9         74 my %mt = qw(audio PCMU/8000 rfc2833 telephone-event/8000);
625 9   50     138 my $mt = $param->{dtmf_methods} || 'audio,rfc2833';
626 9         30 my (%rmap,%pargs);
627 9         154 for($mt =~m{([\w+\-]+)}g) {
628 18 50       70 my $type = $mt{$_} or die "invalid dtmf_method: $_";
629 18         92 $rmap{$type} = $_.'_type';
630             # 0 is default type for PCMU/8000
631 18 100       148 %pargs = (audio_type => 0) if $_ eq 'audio';
632             }
633 9         26 for my $l (@{$m->{lines}}) {
  9         67  
634 27 100       75 $l->[0] eq 'a' or next;
635 18 100       111 my ($type,$name) = $l->[1] =~m{^rtpmap:(\d+)\s+(\S+)} or next;
636 9 50       31 my $pname = $rmap{$name} or next;
637 9         60 $pargs{$pname} = $type;
638             }
639 9 50       166 $media_dtmfxtract[$i] = dtmf_extractor(%pargs) if %pargs;
640             }
641             }
642             }
643              
644 44 100       366 $param->{media_dtmfxtract} = @media_dtmfxtract ? \@media_dtmfxtract :undef;
645              
646 44         187 return 1;
647             }
648              
649             ###########################################################################
650             # setup local RTP socks
651             # Args: $self
652             # Returns: NONE
653             # Comments: set sdp,media_lsocks,media_ssocks in self->{param}
654             ###########################################################################
655             sub _setup_local_rtp_socks {
656 52     52   394 my Net::SIP::Simple::Call $self = shift;
657 52         276 my $param = $self->{param};
658              
659 52         144 my $call_on_hold = $param->{call_on_hold};
660 52         313 $param->{call_on_hold} = 0; # one-shot
661              
662 52   66     704 my $sdp = $param->{_sdp_saved} || $param->{sdp};
663 52 50 66     368 if ( $sdp && !UNIVERSAL::isa( $sdp,'Net::SIP::SDP' )) {
664 0         0 $sdp = Net::SIP::SDP->new( $sdp );
665             }
666              
667 52         468 my $laddr = $param->{leg}->laddr(0);
668 52 100       174 if ( !$sdp ) {
669             # create SDP body
670 48         111 my $raddr = $param->{media_rsocks};
671              
672             # if no raddr yet just assume one
673 48         130 my @media;
674 48         136 my $rp = $param->{rtp_param};
675 48 100       197 if ( my $sdp_peer = $param->{sdp_peer} ) {
676 13         80 foreach my $m ( $sdp_peer->get_media ) {
677 13 50       142 if ( $m->{proto} ne 'RTP/AVP' ) {
678 0         0 $self->error( "only RTP/AVP supported" );
679 0         0 return;
680             }
681 13         45 my @a;
682 13 50       67 if ( $m->{media} eq 'audio' ) {
683             # enforce the payload type based on rtp_param
684 13         155 $m = { %$m, fmt => $rp->[0] };
685 13 50       84 push @a, (
686             "rtpmap:$rp->[0] $rp->[3]",
687             "ptime:".$rp->[2]*1000
688             ) if $rp->[3];
689 13         207 push @a, (
690             "rtpmap:101 telephone-event/8000",
691             "fmtp:101 0-16"
692             );
693             }
694             push @media, {
695             media => $m->{media},
696             proto => $m->{proto},
697             range => $m->{range},
698 13         218 fmt => [ $m->{fmt},101 ],
699             a => \@a,
700             };
701             }
702             } else {
703 35         116 my @a;
704 35 50       123 push @a,( "rtpmap:$rp->[0] $rp->[3]" , "ptime:".$rp->[2]*1000) if $rp->[3];
705 35 50 33     156 my $te = $rp->[3] && $rp->[0] == 101 ? 102: 101;
706 35         289 push @a, ( "rtpmap:$te telephone-event/8000","fmtp:$te 0-16" );
707 35   50     1855 push @media, {
708             proto => 'RTP/AVP',
709             media => 'audio',
710             fmt => [ $rp->[0] || 0, $te ],
711             a => \@a,
712             }
713             }
714              
715 48         622 my $lsocks = $param->{media_lsocks} = [];
716 48         320 foreach my $m (@media) {
717             my ($port,@socks) = create_rtp_sockets( $laddr,$m->{range} )
718 48 50       582 or die $!;
719 48 50       290 push @$lsocks, @socks == 1 ? $socks[0] : \@socks;
720 48         227 $m->{port} = $port;
721             }
722              
723 48         1526 $sdp = $param->{sdp} = Net::SIP::SDP->new(
724             { addr => $laddr },
725             @media
726             );
727             }
728              
729 52 50       294 unless ( $param->{media_lsocks} ) {
730             # SDP body was provided, but sockets not
731 0         0 croak( 'not supported: if you provide SDP body you need to provide sockets too' );
732             }
733              
734             # asymetric_rtp, e.g. source socket of packet to peer is not the socket where RTP
735             # from peer gets received
736 52 50 33     724 if ( !$param->{media_ssocks} && $param->{asymetric_rtp} ) {
737             my @arg = (
738             Proto => 'udp',
739 0   0     0 LocalAddr => ( $param->{rtp_addr} || $laddr )
740             );
741 0         0 my $msocks = $param->{media_ssocks} = [];
742 0         0 foreach my $m (@{ $param->{media_lsocks} }) {
  0         0  
743 0         0 my $socks;
744 0 0       0 if ( UNIVERSAL::isa( $m,'ARRAY' )) {
745 0         0 $socks = [];
746 0         0 foreach my $sock (@$m) {
747 0   0     0 push @$socks, INETSOCK(@arg) || die $!;
748             }
749             } else {
750 0   0     0 $socks = INETSOCK(@arg) || die $!;
751             }
752 0         0 push @$msocks,$socks;
753             }
754             }
755              
756 52         443 $param->{_sdp_saved} = $sdp;
757 52 50       257 if ( $call_on_hold ) {
758 0           $sdp = dclone($sdp); # make changes on clone
759 0           my @new = map { [ '0.0.0.0',$_->{port} ] } $sdp->get_media;
  0            
760 0           $sdp->replace_media_listen( @new );
761 0           $param->{sdp} = $sdp;
762             }
763             }
764              
765             1;