File Coverage

blib/lib/Net/SIP/Simple/Call.pm
Criterion Covered Total %
statement 271 352 76.9
branch 91 146 62.3
condition 58 121 47.9
subroutine 26 31 83.8
pod 12 12 100.0
total 458 662 69.1


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 43     43   275 use strict;
  43         76  
  43         1156  
9 43     43   204 use warnings;
  43         74  
  43         1386  
10              
11             package Net::SIP::Simple::Call;
12 43     43   197 use base 'Net::SIP::Simple';
  43         80  
  43         6908  
13 43     43   282 use fields qw( call_cleanup rtp_cleanup ctx param );
  43         112  
  43         347  
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 43     43   3872 use Net::SIP::Util qw(:all);
  43         108  
  43         7243  
62 43     43   279 use Net::SIP::Debug;
  43         78  
  43         227  
63 43     43   304 use Net::SIP::DTMF 'dtmf_extractor';
  43         80  
  43         2456  
64 43     43   251 use Socket;
  43         76  
  43         18246  
65 43     43   279 use Storable 'dclone';
  43         82  
  43         2300  
66 43     43   219 use Carp 'croak';
  43         71  
  43         1697  
67 43     43   329 use Scalar::Util 'weaken';
  43         81  
  43         145870  
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 53     53 1 239 my ($class,$control,$ctx,$param) = @_;
80 53         174 my $self = fields::new( $class );
81 53         13255 %$self = %$control;
82              
83 53         188 $self->{ua_cleanup} = [];
84 53 100       336 $ctx = { to => $ctx } if ! ref($ctx);
85 53   66     563 $ctx->{from} ||= $self->{from};
86 53   33     532 $ctx->{contact} ||= $self->{contact};
87 53   66     318 $ctx->{auth} ||= $self->{auth};
88 53   33     331 $ctx->{route} ||= $self->{route};
89 53         102 $self->{ctx} = $ctx;
90              
91 53         129 $self->{call_cleanup} = [];
92 53         119 $self->{rtp_cleanup} = [];
93 53   100     298 $self->{param} = $param ||= {};
94 53   66     1173 $param->{init_media} ||= $self->rtp( 'media_recv_echo' );
95 53   50     599 $param->{rtp_param} ||= [ 0,160,160/8000 ]; # PCMU/8000: 50*160 bytes/second
96 53   50     540 $param->{dtmf_events} ||= []; # get added by sub dtmf
97              
98 53 100       169 if (my $cb = delete $param->{cb_cleanup}) {
99 13         45 push @{$self->{call_cleanup}}, $cb;
  13         73  
100             }
101 53         172 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 45     45 1 108 my Net::SIP::Simple::Call $self = shift;
112 45         634 $self->rtp_cleanup;
113 45         93 while ( my $cb = shift @{ $self->{call_cleanup} } ) {
  58         6764  
114 13         56 invoke_callback($cb,$self)
115             }
116 45 50       189 if (my $ctx = delete $self->{ctx}) {
117 45         298 $self->{endpoint}->close_context( $ctx );
118             }
119 45         175 $self->{param} = {};
120             }
121              
122             sub rtp_cleanup {
123 93     93 1 203 my Net::SIP::Simple::Call $self = shift;
124 93         218 while ( my $cb = shift @{ $self->{rtp_cleanup} } ) {
  189         1758  
125 96         270 invoke_callback($cb,$self)
126             }
127 93         452 DEBUG( 100,"done" );
128             }
129              
130             sub DESTROY {
131 50     50   2576 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 6     6 1 15 my Net::SIP::Simple::Call $self = shift;
152 6         34 my %args = @_;
153 6         28 @{ $self->{param} }{ keys %args } = values %args;
  6         111  
154 6         43 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 38     38 1 1000397 my Net::SIP::Simple::Call $self = shift;
180 38         169 my %args = @_;
181              
182 38         122 my $param = $self->{param};
183 38         104 my $clear_sdp = delete $args{clear_sdp};
184 38 100       152 $clear_sdp = $param->{clear_sdp} if ! defined $clear_sdp;
185 38 100       98 if ( $clear_sdp ) {
186             # clear SDP keys so that a new SDP session will be created
187 4         11 @{ $param }{qw( sdp _sdp_saved sdp_peer media_ssocks media_lsocks )} = ()
  4         243  
188             }
189 38 100       539 $self->{param} = $param = { %$param, %args } if %args;
190              
191              
192 38         101 my $leg = $param->{leg};
193 38 100       124 if ( ! $leg ) {
194 35         271 ($leg) = $self->{dispatcher}->get_legs();
195 35         91 $param->{leg} = $leg;
196             }
197              
198 38         93 my $ctx = $self->{ctx};
199              
200 38         69 my $sdp;
201 38 50       128 if ( ! $param->{sdp_on_ack} ) {
202 38         464 $self->_setup_local_rtp_socks;
203             $sdp = $param->{sdp}
204 38         77 }
205              
206             # predefined callback
207             my $cb = sub {
208 106   50 106   339 my Net::SIP::Simple::Call $self = shift || return;
209 106         347 my ($endpoint,$ctx,$errno,$code,$packet,$leg,$from,$ack) = @_;
210              
211 106 100       304 if ( $errno ) {
212 7 100 66     322 if (!$code || $code != 487) {
213 1 50       19 $self->error( "Failed with error $errno".( $code ? " code=$code" :"" ) );
214             } else {
215             # code 487: request was canceled, probably be me -> ignore
216             }
217 7         48 invoke_callback( $param->{cb_final}, 'FAIL',$self,errno => $errno,
218             code => $code,packet => $packet );
219 7         1330 return;
220             }
221              
222             # new requests in existing call are handled in receive()
223 99 100       354 return $self->receive( @_ ) if $packet->is_request;
224              
225             # response to INVITE
226             # all other responses will not be propagated to this callback
227 93         268 my $param = $self->{param};
228 93 100       1095 if ( $code =~m{^1\d\d} ) {
    50          
229             # preliminary response, ignore
230 63         230 DEBUG(10,"got preliminary response of %s|%s to INVITE",$code,$packet->msg );
231 63         406 invoke_callback( $param->{cb_preliminary},$self,$code,$packet );
232 63         3567 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 30         222 $self->rtp_cleanup;
242              
243 30 50       156 $self->_setup_peer_rtp_socks( $packet ) || do {
244 0         0 invoke_callback( $param->{cb_final},'FAIL',$self );
245 0         0 return;
246             };
247 30 50 33     167 if ( $param->{sdp_on_ack} && $ack ) {
248 0         0 $self->_setup_local_rtp_socks;
249 0         0 $ack->set_body( $param->{sdp} );
250             }
251 30         224 invoke_callback( $param->{cb_final},'OK',$self, packet => $packet );
252 30         107 invoke_callback( $param->{init_media},$self,$param );
253 38         869 };
254              
255              
256 38         94 my $stopvar = 0;
257 38   100     599 $param->{cb_final} ||= \$stopvar;
258 38         95 $cb = [ $cb,$self ];
259 38         156 weaken( $cb->[1] );
260             $self->{ctx} = $self->{endpoint}->invite(
261             $ctx, $cb, $sdp,
262 38 50       364 $param->{sip_header} ? %{ $param->{sip_header} } : ()
  0         0  
263             );
264              
265 38 100       181 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         48 my $noanswercb;
270 27 50       90 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         223 $self->loop( \$stopvar );
299             }
300              
301 27         90 $param->{cb_final} = undef;
302             }
303 38         421 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 4344 my Net::SIP::Simple::Call $self = shift;
319 6         22 my %args = @_;
320              
321 6         16 my $cb = delete $args{cb_final};
322 6         11 %args = ( %{ $self->{param} }, %args );
  6         101  
323 6   33     109 $cb ||= $args{send_cancel};
324              
325             my $cancel_cb = [
326             sub {
327 6   50 6   22 my Net::SIP::Simple::Call $self = shift || return;
328 6         18 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     114 if ( $code && $code =~m{^1\d\d} ) {
334 0         0 DEBUG( 10,"got prelimary response for CANCEL" );
335 0         0 return;
336             }
337 6         27 invoke_callback( $cb,$args );
338             },
339 6         42 $self,$cb,\%args
340             ];
341 6         33 weaken( $cancel_cb->[1] );
342              
343 6         44 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 1000304 my Net::SIP::Simple::Call $self = shift;
358 27         138 my %args = @_;
359              
360 27         90 my $cb = delete $args{cb_final};
361 27         59 %args = ( %{ $self->{param} }, %args );
  27         589  
362 27   33     148 $cb ||= $args{send_bye};
363              
364             my $bye_cb = [
365             sub {
366 27   50 27   101 my Net::SIP::Simple::Call $self = shift || return;
367 27         99 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     364 if ( $code && $code =~m{^1\d\d} ) {
374 0         0 DEBUG( 10,"got prelimary response for BYE" );
375 0         0 return;
376             }
377 27         157 invoke_callback( $cb,$args );
378 27         123 $self->cleanup;
379             },
380 27         666 $self,$cb,\%args
381             ];
382 27         199 weaken( $bye_cb->[1] );
383              
384 27         277 $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 115 my ($self,$events,%args) = @_;
444 12   50     62 my $duration = $args{duration} || 100;
445 12   50     104 my @methods = split(m{[\s,]+}, lc($args{methods}||'rfc2833,audio'));
446              
447 12         28 my %payload_type;
448 12   66     133 while ( ! %payload_type
449             and my $m = shift(@methods)) {
450 12         32 my $type;
451 12 100       59 if ( $m eq 'rfc2833' ) {
    50          
452             $type = $self->{param}{sdp_peer}
453 6   33     104 && $self->{param}{sdp_peer}->name2int('telephone-event/8000','audio');
454             } elsif ( $m eq 'audio' ) {
455             $type = $self->{param}{sdp_peer}
456 6   50     111 && $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       95 %payload_type = ( $m."_type" => $type ) if defined $type;
462             }
463 12 50       37 %payload_type or croak("no usable DTMF method found");
464              
465 12         32 my $arr = $self->{param}{dtmf_events};
466 12         22 my $lastev;
467 12         52 for( split('',$events)) {
468 48 50       158 if ( m{[\dA-D*#]} ) {
469 48 100       99 if (defined $lastev) {
470             # force some silence to distinguish DTMF
471 36 50       121 push @$arr, {
472             duration => ($lastev eq $_) ? 100 : 50,
473             %payload_type
474             }
475             }
476 48         168 push @$arr, {
477             event => $_,
478             duration => $duration,
479             %payload_type,
480             };
481 48         96 $lastev = $_;
482             } else {
483             # pause
484 0         0 push @$arr, { duration => $duration, %payload_type };
485 0         0 $lastev = undef;
486             }
487             }
488 12 50       43 if ( my $cb_final = $args{cb_final} ) {
489 0         0 push @$arr, { cb_final => $cb_final }
490             } else {
491 12         43 my $stopvar;
492 12         45 push @$arr, { cb_final => \$stopvar };
493 12         74 $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 54     54 1 275 my ($self,$endpoint,$ctx,$error,$code,$packet,$leg,$from) = @_;
511 54 50       347 if ( ! $packet ) {
    50          
512 0         0 $self->error( "error occurred: $error" );
513             } elsif ( $packet->is_request ) {
514 54         189 my $method = $packet->method;
515 54         209 my $param = $self->{param};
516              
517 54 100 100     1671 if ( $method eq 'BYE' || $method eq 'CANCEL' ) {
    50 66        
    0          
    0          
518             # tear down
519 18         143 $self->cleanup;
520 18         114 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 36 100       102 if ( my $sdp_peer = eval { $packet->sdp_body } ) {
  36 50       265  
527 18         111 DEBUG( 50,"got sdp data from peer: ".$sdp_peer->as_string );
528 18         175 $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 36 100       516 if ( $method eq 'INVITE' ) {
    50          
536              
537 18 50       82 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 18   66     267 $param->{leg} ||= $leg;
543 18         171 $self->_setup_local_rtp_socks;
544 18         115 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 18 50 33     302 if ! $resp || ! UNIVERSAL::isa($resp,'Net::SIP::Packet');
549 18         128 DEBUG( 100,'created response '.$resp->as_string );
550 18         128 $self->{endpoint}->new_response( $ctx,$resp,$leg,$from );
551              
552             } elsif ( $method eq 'ACK' ) {
553 18         118 $self->rtp_cleanup; # close last RTP session
554 18         190 invoke_callback($param->{cb_established},'OK',$self);
555 18         8312 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 48     48   118 my Net::SIP::Simple::Call $self = shift;
587 48         129 my $param = $self->{param};
588 48   33     157 my $data = shift || $param->{sdp_peer};
589              
590 48         94 my $sdp_peer;
591 48 100       303 if ( UNIVERSAL::isa( $data, 'Net::SIP::Packet' )) {
592 30 50       388 $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 18         50 $sdp_peer = $data
598             }
599              
600 48         315 $param->{sdp_peer} = $sdp_peer;
601              
602 48         641 my @media = $sdp_peer->get_media;
603 48         145 my $ls = $param->{media_lsocks};
604 48 50 66     724 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 48         318 my $raddr = $param->{media_raddr} = [];
610 48         112 my @media_dtmfxtract;
611 48         190 for( my $i=0;$i<@media;$i++) {
612 48         100 my $m = $media[$i];
613 48   50     275 my $range = $m->{range} || 1;
614 48         602 my $paddr = ip_canonical($m->{addr});
615 48 100 66     831 if (!$m->{port} or $paddr eq '0.0.0.0' or $paddr eq '::') {
      66        
616             # on-hold for this media
617 1         4 push @$raddr, undef;
618             } else {
619 47         199 my @socks = map { ip_parts2sockaddr($m->{addr},$m->{port}+$_) }
  94         422  
620             (0..$range-1);
621 47 50       249 push @$raddr, @socks == 1 ? $socks[0] : \@socks;
622              
623 47 100 66     626 if ( $m->{media} eq 'audio' and $param->{cb_dtmf} ) {
624 9         65 my %mt = qw(audio PCMU/8000 rfc2833 telephone-event/8000);
625 9   50     153 my $mt = $param->{dtmf_methods} || 'audio,rfc2833';
626 9         32 my (%rmap,%pargs);
627 9         132 for($mt =~m{([\w+\-]+)}g) {
628 18 50       66 my $type = $mt{$_} or die "invalid dtmf_method: $_";
629 18         75 $rmap{$type} = $_.'_type';
630             # 0 is default type for PCMU/8000
631 18 100       109 %pargs = (audio_type => 0) if $_ eq 'audio';
632             }
633 9         23 for my $l (@{$m->{lines}}) {
  9         57  
634 27 100       67 $l->[0] eq 'a' or next;
635 18 100       420 my ($type,$name) = $l->[1] =~m{^rtpmap:(\d+)\s+(\S+)} or next;
636 9 50       36 my $pname = $rmap{$name} or next;
637 9         27 $pargs{$pname} = $type;
638             }
639 9 50       127 $media_dtmfxtract[$i] = dtmf_extractor(%pargs) if %pargs;
640             }
641             }
642             }
643              
644 48 100       271 $param->{media_dtmfxtract} = @media_dtmfxtract ? \@media_dtmfxtract :undef;
645              
646 48         185 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 56     56   173 my Net::SIP::Simple::Call $self = shift;
657 56         197 my $param = $self->{param};
658              
659 56         120 my $call_on_hold = $param->{call_on_hold};
660 56         390 $param->{call_on_hold} = 0; # one-shot
661              
662 56   66     609 my $sdp = $param->{_sdp_saved} || $param->{sdp};
663 56 50 66     315 if ( $sdp && !UNIVERSAL::isa( $sdp,'Net::SIP::SDP' )) {
664 0         0 $sdp = Net::SIP::SDP->new( $sdp );
665             }
666              
667 56         379 my $laddr = $param->{leg}->laddr(0);
668 56 100       203 if ( !$sdp ) {
669             # create SDP body
670 52         153 my $raddr = $param->{media_rsocks};
671              
672             # if no raddr yet just assume one
673 52         139 my @media;
674 52         118 my $rp = $param->{rtp_param};
675 52 100       222 if ( my $sdp_peer = $param->{sdp_peer} ) {
676 15         99 foreach my $m ( $sdp_peer->get_media ) {
677 15 50       115 if ( $m->{proto} ne 'RTP/AVP' ) {
678 0         0 $self->error( "only RTP/AVP supported" );
679 0         0 return;
680             }
681 15         68 my @a;
682 15 50       77 if ( $m->{media} eq 'audio' ) {
683             # enforce the payload type based on rtp_param
684 15         132 $m = { %$m, fmt => $rp->[0] };
685 15 50       66 push @a, (
686             "rtpmap:$rp->[0] $rp->[3]",
687             "ptime:".$rp->[2]*1000
688             ) if $rp->[3];
689 15         176 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 15         207 fmt => [ $m->{fmt},101 ],
699             a => \@a,
700             };
701             }
702             } else {
703 37         123 my @a;
704 37 50       124 push @a,( "rtpmap:$rp->[0] $rp->[3]" , "ptime:".$rp->[2]*1000) if $rp->[3];
705 37 50 33     205 my $te = $rp->[3] && $rp->[0] == 101 ? 102: 101;
706 37         241 push @a, ( "rtpmap:$te telephone-event/8000","fmtp:$te 0-16" );
707 37   50     1309 push @media, {
708             proto => 'RTP/AVP',
709             media => 'audio',
710             fmt => [ $rp->[0] || 0, $te ],
711             a => \@a,
712             }
713             }
714              
715 52         464 my $lsocks = $param->{media_lsocks} = [];
716 52         274 foreach my $m (@media) {
717             my ($port,@socks) = create_rtp_sockets( $laddr,$m->{range} )
718 52 50       567 or die $!;
719 52 50       284 push @$lsocks, @socks == 1 ? $socks[0] : \@socks;
720 52         167 $m->{port} = $port;
721             }
722              
723 52         1175 $sdp = $param->{sdp} = Net::SIP::SDP->new(
724             { addr => $laddr },
725             @media
726             );
727             }
728              
729 56 50       373 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 56 50 33     667 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 56         355 $param->{_sdp_saved} = $sdp;
757 56 100       257 if ( $call_on_hold ) {
758 1         188 $sdp = dclone($sdp); # make changes on clone
759 1         9 my @new = map { [ '0.0.0.0',$_->{port} ] } $sdp->get_media;
  1         7  
760 1         62 $sdp->replace_media_listen( @new );
761 1         6 $param->{sdp} = $sdp;
762             }
763             }
764              
765             1;