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   285 use strict;
  43         132  
  43         1171  
9 43     43   299 use warnings;
  43         68  
  43         1422  
10              
11             package Net::SIP::Simple::Call;
12 43     43   220 use base 'Net::SIP::Simple';
  43         80  
  43         7467  
13 43     43   290 use fields qw( call_cleanup rtp_cleanup ctx param );
  43         114  
  43         355  
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   4081 use Net::SIP::Util qw(:all);
  43         94  
  43         7297  
62 43     43   270 use Net::SIP::Debug;
  43         77  
  43         266  
63 43     43   272 use Net::SIP::DTMF 'dtmf_extractor';
  43         85  
  43         2585  
64 43     43   294 use Socket;
  43         90  
  43         18551  
65 43     43   274 use Storable 'dclone';
  43         82  
  43         2429  
66 43     43   259 use Carp 'croak';
  43         72  
  43         1820  
67 43     43   239 use Scalar::Util 'weaken';
  43         92  
  43         144625  
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 2392 my ($class,$control,$ctx,$param) = @_;
80 53         272 my $self = fields::new( $class );
81 53         12316 %$self = %$control;
82              
83 53         200 $self->{ua_cleanup} = [];
84 53 100       451 $ctx = { to => $ctx } if ! ref($ctx);
85 53   66     920 $ctx->{from} ||= $self->{from};
86 53   33     497 $ctx->{contact} ||= $self->{contact};
87 53   66     264 $ctx->{auth} ||= $self->{auth};
88 53   33     622 $ctx->{route} ||= $self->{route};
89 53         95 $self->{ctx} = $ctx;
90              
91 53         100 $self->{call_cleanup} = [];
92 53         107 $self->{rtp_cleanup} = [];
93 53   100     351 $self->{param} = $param ||= {};
94 53   66     1222 $param->{init_media} ||= $self->rtp( 'media_recv_echo' );
95 53   50     826 $param->{rtp_param} ||= [ 0,160,160/8000 ]; # PCMU/8000: 50*160 bytes/second
96 53   50     435 $param->{dtmf_events} ||= []; # get added by sub dtmf
97              
98 53 100       227 if (my $cb = delete $param->{cb_cleanup}) {
99 13         33 push @{$self->{call_cleanup}}, $cb;
  13         44  
100             }
101 53         155 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 99 my Net::SIP::Simple::Call $self = shift;
112 45         449 $self->rtp_cleanup;
113 45         77 while ( my $cb = shift @{ $self->{call_cleanup} } ) {
  58         14859  
114 13         64 invoke_callback($cb,$self)
115             }
116 45 50       185 if (my $ctx = delete $self->{ctx}) {
117 45         272 $self->{endpoint}->close_context( $ctx );
118             }
119 45         182 $self->{param} = {};
120             }
121              
122             sub rtp_cleanup {
123 93     93 1 226 my Net::SIP::Simple::Call $self = shift;
124 93         184 while ( my $cb = shift @{ $self->{rtp_cleanup} } ) {
  189         1510  
125 96         273 invoke_callback($cb,$self)
126             }
127 93         333 DEBUG( 100,"done" );
128             }
129              
130             sub DESTROY {
131 50     50   3447 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         36 my %args = @_;
153 6         23 @{ $self->{param} }{ keys %args } = values %args;
  6         113  
154 6         39 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 1000583 my Net::SIP::Simple::Call $self = shift;
180 38         163 my %args = @_;
181              
182 38         95 my $param = $self->{param};
183 38         107 my $clear_sdp = delete $args{clear_sdp};
184 38 100       150 $clear_sdp = $param->{clear_sdp} if ! defined $clear_sdp;
185 38 100       134 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         433  
188             }
189 38 100       583 $self->{param} = $param = { %$param, %args } if %args;
190              
191              
192 38         104 my $leg = $param->{leg};
193 38 100       127 if ( ! $leg ) {
194 35         304 ($leg) = $self->{dispatcher}->get_legs();
195 35         88 $param->{leg} = $leg;
196             }
197              
198 38         78 my $ctx = $self->{ctx};
199              
200 38         98 my $sdp;
201 38 50       150 if ( ! $param->{sdp_on_ack} ) {
202 38         610 $self->_setup_local_rtp_socks;
203             $sdp = $param->{sdp}
204 38         79 }
205              
206             # predefined callback
207             my $cb = sub {
208 108   50 108   369 my Net::SIP::Simple::Call $self = shift || return;
209 108         352 my ($endpoint,$ctx,$errno,$code,$packet,$leg,$from,$ack) = @_;
210              
211 108 100       300 if ( $errno ) {
212 7 100 66     201 if (!$code || $code != 487) {
213 1 50       23 $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         239 return;
220             }
221              
222             # new requests in existing call are handled in receive()
223 101 100       382 return $self->receive( @_ ) if $packet->is_request;
224              
225             # response to INVITE
226             # all other responses will not be propagated to this callback
227 95         280 my $param = $self->{param};
228 95 100       1099 if ( $code =~m{^1\d\d} ) {
    50          
229             # preliminary response, ignore
230 65         280 DEBUG(10,"got preliminary response of %s|%s to INVITE",$code,$packet->msg );
231 65         377 invoke_callback( $param->{cb_preliminary},$self,$code,$packet );
232 65         14580 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         208 $self->rtp_cleanup;
242              
243 30 50       242 $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     158 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         170 invoke_callback( $param->{cb_final},'OK',$self, packet => $packet );
252 30         295 invoke_callback( $param->{init_media},$self,$param );
253 38         837 };
254              
255              
256 38         105 my $stopvar = 0;
257 38   100     562 $param->{cb_final} ||= \$stopvar;
258 38         90 $cb = [ $cb,$self ];
259 38         170 weaken( $cb->[1] );
260             $self->{ctx} = $self->{endpoint}->invite(
261             $ctx, $cb, $sdp,
262 38 50       440 $param->{sip_header} ? %{ $param->{sip_header} } : ()
  0         0  
263             );
264              
265 38 100       197 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         43 my $noanswercb;
270 27 50       89 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         311 $self->loop( \$stopvar );
299             }
300              
301 27         91 $param->{cb_final} = undef;
302             }
303 38         412 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 4350 my Net::SIP::Simple::Call $self = shift;
319 6         18 my %args = @_;
320              
321 6         15 my $cb = delete $args{cb_final};
322 6         15 %args = ( %{ $self->{param} }, %args );
  6         157  
323 6   33     116 $cb ||= $args{send_cancel};
324              
325             my $cancel_cb = [
326             sub {
327 6   50 6   24 my Net::SIP::Simple::Call $self = shift || return;
328 6         20 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     83 if ( $code && $code =~m{^1\d\d} ) {
334 0         0 DEBUG( 10,"got prelimary response for CANCEL" );
335 0         0 return;
336             }
337 6         29 invoke_callback( $cb,$args );
338             },
339 6         120 $self,$cb,\%args
340             ];
341 6         30 weaken( $cancel_cb->[1] );
342              
343 6         39 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 1000302 my Net::SIP::Simple::Call $self = shift;
358 27         149 my %args = @_;
359              
360 27         85 my $cb = delete $args{cb_final};
361 27         60 %args = ( %{ $self->{param} }, %args );
  27         481  
362 27   33     140 $cb ||= $args{send_bye};
363              
364             my $bye_cb = [
365             sub {
366 27   50 27   99 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     222 if ( $code && $code =~m{^1\d\d} ) {
374 0         0 DEBUG( 10,"got prelimary response for BYE" );
375 0         0 return;
376             }
377 27         138 invoke_callback( $cb,$args );
378 27         128 $self->cleanup;
379             },
380 27         618 $self,$cb,\%args
381             ];
382 27         200 weaken( $bye_cb->[1] );
383              
384 27         385 $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 107 my ($self,$events,%args) = @_;
444 12   50     61 my $duration = $args{duration} || 100;
445 12   50     88 my @methods = split(m{[\s,]+}, lc($args{methods}||'rfc2833,audio'));
446              
447 12         26 my %payload_type;
448 12   66     115 while ( ! %payload_type
449             and my $m = shift(@methods)) {
450 12         23 my $type;
451 12 100       72 if ( $m eq 'rfc2833' ) {
    50          
452             $type = $self->{param}{sdp_peer}
453 6   33     85 && $self->{param}{sdp_peer}->name2int('telephone-event/8000','audio');
454             } elsif ( $m eq 'audio' ) {
455             $type = $self->{param}{sdp_peer}
456 6   50     68 && $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       151 %payload_type = ( $m."_type" => $type ) if defined $type;
462             }
463 12 50       24 %payload_type or croak("no usable DTMF method found");
464              
465 12         428 my $arr = $self->{param}{dtmf_events};
466 12         27 my $lastev;
467 12         49 for( split('',$events)) {
468 48 50       181 if ( m{[\dA-D*#]} ) {
469 48 100       81 if (defined $lastev) {
470             # force some silence to distinguish DTMF
471 36 50       113 push @$arr, {
472             duration => ($lastev eq $_) ? 100 : 50,
473             %payload_type
474             }
475             }
476 48         189 push @$arr, {
477             event => $_,
478             duration => $duration,
479             %payload_type,
480             };
481 48         121 $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         17 my $stopvar;
492 12         37 push @$arr, { cb_final => \$stopvar };
493 12         68 $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 365 my ($self,$endpoint,$ctx,$error,$code,$packet,$leg,$from) = @_;
511 54 50       365 if ( ! $packet ) {
    50          
512 0         0 $self->error( "error occurred: $error" );
513             } elsif ( $packet->is_request ) {
514 54         157 my $method = $packet->method;
515 54         168 my $param = $self->{param};
516              
517 54 100 100     615 if ( $method eq 'BYE' || $method eq 'CANCEL' ) {
    50 66        
    0          
    0          
518             # tear down
519 18         119 $self->cleanup;
520 18         110 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       83 if ( my $sdp_peer = eval { $packet->sdp_body } ) {
  36 50       291  
527 18         168 DEBUG( 50,"got sdp data from peer: ".$sdp_peer->as_string );
528 18         164 $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       211 if ( $method eq 'INVITE' ) {
    50          
536              
537 18 50       77 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     454 $param->{leg} ||= $leg;
543 18         190 $self->_setup_local_rtp_socks;
544 18         139 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     202 if ! $resp || ! UNIVERSAL::isa($resp,'Net::SIP::Packet');
549 18         119 DEBUG( 100,'created response '.$resp->as_string );
550 18         132 $self->{endpoint}->new_response( $ctx,$resp,$leg,$from );
551              
552             } elsif ( $method eq 'ACK' ) {
553 18         134 $self->rtp_cleanup; # close last RTP session
554 18         314 invoke_callback($param->{cb_established},'OK',$self);
555 18         24858 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         121 my $param = $self->{param};
588 48   33     156 my $data = shift || $param->{sdp_peer};
589              
590 48         75 my $sdp_peer;
591 48 100       295 if ( UNIVERSAL::isa( $data, 'Net::SIP::Packet' )) {
592 30 50       252 $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         53 $sdp_peer = $data
598             }
599              
600 48         334 $param->{sdp_peer} = $sdp_peer;
601              
602 48         423 my @media = $sdp_peer->get_media;
603 48         141 my $ls = $param->{media_lsocks};
604 48 50 66     718 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         239 my $raddr = $param->{media_raddr} = [];
610 48         97 my @media_dtmfxtract;
611 48         176 for( my $i=0;$i<@media;$i++) {
612 48         115 my $m = $media[$i];
613 48   50     329 my $range = $m->{range} || 1;
614 48         950 my $paddr = ip_canonical($m->{addr});
615 48 100 66     915 if (!$m->{port} or $paddr eq '0.0.0.0' or $paddr eq '::') {
      66        
616             # on-hold for this media
617 1         3 push @$raddr, undef;
618             } else {
619 47         200 my @socks = map { ip_parts2sockaddr($m->{addr},$m->{port}+$_) }
  94         399  
620             (0..$range-1);
621 47 50       252 push @$raddr, @socks == 1 ? $socks[0] : \@socks;
622              
623 47 100 66     896 if ( $m->{media} eq 'audio' and $param->{cb_dtmf} ) {
624 9         71 my %mt = qw(audio PCMU/8000 rfc2833 telephone-event/8000);
625 9   50     99 my $mt = $param->{dtmf_methods} || 'audio,rfc2833';
626 9         26 my (%rmap,%pargs);
627 9         104 for($mt =~m{([\w+\-]+)}g) {
628 18 50       61 my $type = $mt{$_} or die "invalid dtmf_method: $_";
629 18         52 $rmap{$type} = $_.'_type';
630             # 0 is default type for PCMU/8000
631 18 100       146 %pargs = (audio_type => 0) if $_ eq 'audio';
632             }
633 9         21 for my $l (@{$m->{lines}}) {
  9         69  
634 27 100       72 $l->[0] eq 'a' or next;
635 18 100       208 my ($type,$name) = $l->[1] =~m{^rtpmap:(\d+)\s+(\S+)} or next;
636 9 50       52 my $pname = $rmap{$name} or next;
637 9         30 $pargs{$pname} = $type;
638             }
639 9 50       99 $media_dtmfxtract[$i] = dtmf_extractor(%pargs) if %pargs;
640             }
641             }
642             }
643              
644 48 100       329 $param->{media_dtmfxtract} = @media_dtmfxtract ? \@media_dtmfxtract :undef;
645              
646 48         179 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   328 my Net::SIP::Simple::Call $self = shift;
657 56         196 my $param = $self->{param};
658              
659 56         115 my $call_on_hold = $param->{call_on_hold};
660 56         354 $param->{call_on_hold} = 0; # one-shot
661              
662 56   66     651 my $sdp = $param->{_sdp_saved} || $param->{sdp};
663 56 50 66     405 if ( $sdp && !UNIVERSAL::isa( $sdp,'Net::SIP::SDP' )) {
664 0         0 $sdp = Net::SIP::SDP->new( $sdp );
665             }
666              
667 56         372 my $laddr = $param->{leg}->laddr(0);
668 56 100       177 if ( !$sdp ) {
669             # create SDP body
670 52         108 my $raddr = $param->{media_rsocks};
671              
672             # if no raddr yet just assume one
673 52         91 my @media;
674 52         104 my $rp = $param->{rtp_param};
675 52 100       188 if ( my $sdp_peer = $param->{sdp_peer} ) {
676 15         667 foreach my $m ( $sdp_peer->get_media ) {
677 15 50       116 if ( $m->{proto} ne 'RTP/AVP' ) {
678 0         0 $self->error( "only RTP/AVP supported" );
679 0         0 return;
680             }
681 15         40 my @a;
682 15 50       91 if ( $m->{media} eq 'audio' ) {
683             # enforce the payload type based on rtp_param
684 15         155 $m = { %$m, fmt => $rp->[0] };
685 15 50       165 push @a, (
686             "rtpmap:$rp->[0] $rp->[3]",
687             "ptime:".$rp->[2]*1000
688             ) if $rp->[3];
689 15         189 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         311 fmt => [ $m->{fmt},101 ],
699             a => \@a,
700             };
701             }
702             } else {
703 37         98 my @a;
704 37 50       111 push @a,( "rtpmap:$rp->[0] $rp->[3]" , "ptime:".$rp->[2]*1000) if $rp->[3];
705 37 50 33     215 my $te = $rp->[3] && $rp->[0] == 101 ? 102: 101;
706 37         302 push @a, ( "rtpmap:$te telephone-event/8000","fmtp:$te 0-16" );
707 37   50     1627 push @media, {
708             proto => 'RTP/AVP',
709             media => 'audio',
710             fmt => [ $rp->[0] || 0, $te ],
711             a => \@a,
712             }
713             }
714              
715 52         549 my $lsocks = $param->{media_lsocks} = [];
716 52         242 foreach my $m (@media) {
717             my ($port,@socks) = create_rtp_sockets( $laddr,$m->{range} )
718 52 50       525 or die $!;
719 52 50       245 push @$lsocks, @socks == 1 ? $socks[0] : \@socks;
720 52         210 $m->{port} = $port;
721             }
722              
723 52         1426 $sdp = $param->{sdp} = Net::SIP::SDP->new(
724             { addr => $laddr },
725             @media
726             );
727             }
728              
729 56 50       260 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     1192 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         385 $param->{_sdp_saved} = $sdp;
757 56 100       345 if ( $call_on_hold ) {
758 1         158 $sdp = dclone($sdp); # make changes on clone
759 1         7 my @new = map { [ '0.0.0.0',$_->{port} ] } $sdp->get_media;
  1         13  
760 1         60 $sdp->replace_media_listen( @new );
761 1         3 $param->{sdp} = $sdp;
762             }
763             }
764              
765             1;