#!/usr/bin/perl use strict; use warnings; use Getopt::Long; use Pod::Usage; use YAML; use Net::SIP; use Net::SIP::Util qw(invoke_callback); use Net::SIP::Debug; use POSIX qw(strftime); my $conf_default; if ($0 =~ m@.*/@) { $conf_default = $& . "config.yaml"; chdir $&; } else { $conf_default = "config.yaml"; } my %opt = ( conf => $conf_default, ); GetOptions( \%opt, 'conf=s', 'help' ) || pod2usage(2); pod2usage(1) if $opt{help}; my ($cfg) = YAML::LoadFile($opt{conf}); die "Fail to read yaml file: $@" if $@; die "Fail to read answer sound: " . $cfg->{answer_sound} unless -f $cfg->{answer_sound}; my $rings = 0; $rings = $cfg->{answer_rings} if $cfg->{answer_rings} =~ /^\d+$/; my @legs; if ($cfg->{sip_legs}) { for (split(/\s+/, $cfg->{sip_legs})) { push @legs, Net::SIP::Leg->new(addr => $_); } } Net::SIP::Debug->level($cfg->{sip_debug_level}) if $cfg->{sip_debug_level}; my $ua = Net::SIP::Simple->new( leg => \@legs, outgoing_proxy => $cfg->{sip_domain}, registrar => $cfg->{sip_domain}, domain => $cfg->{sip_domain}, from => $cfg->{sip_user}, auth => [$cfg->{sip_user}, $cfg->{sip_passwd}], ) || die; my $register; $register = sub { my $expire = $ua->register || die "Fail to register"; $ua->add_timer($expire/2, $register); }; $register->(); $ua->listen( init_media => \&answering, recv_bye => sub { my $param = shift; my $t = delete $param->{stop_rtp_timer}; $t && $t->cancel; } ); if ($rings > 0) { my $sub = $ua->{endpoint}->{application}->[0]; $ua->{endpoint}->{application}->[0] = sub { my ($self, $args, $endpoint, $ctx, $request, $leg, $from) = @_; my $meth = $request->method; if ($meth eq 'INVITE') { my $res = $request->create_response('180', 'Ringing'); $endpoint->new_response($ctx, $res, $leg, $from); $self->add_timer($rings, [$sub, $self, $args, $endpoint, $ctx, $request, $leg, $from]); } else { $endpoint->close_context($ctx); } }; } $ua->loop; exit 0; sub answering { my ($call, $param) = @_; my $answer_fd; my $answer_buf; my $answer = sub { $answer_fd || open($answer_fd, '<', $cfg->{answer_sound}) || die $!; my $buf; $answer_buf = $buf if read($answer_fd, $buf, 160); $answer_buf; }; my $out = $call->get_peer; $out =~ s/\s*\"?\s*\\/\:]//g; $out =~ s/\s+/_/g; $out = sprintf("%s.%s.raw", strftime("%Y%m%d-%H%M%S", localtime), $out); $out = $cfg->{voicemail_dir} . "/$out" if $cfg->{voicemail_dir}; $param->{stop_rtp_timer} = $call->add_timer( $cfg->{voicemail_time}, [sub { shift->bye; }, $call]); return invoke_callback($call->rtp('media_send_recv', $answer, 1, $out), $call, $param); } __END__ =head1 NAME answer_machine - answering machine =head1 SYNOPSIS % answer_machine % answer_machine --conf /path/to/config.yaml =head1 DESCRIPTION C is a command line application that answers to the incoming SIP calls.