From 66ca50e198ed2989b97293fac59de30f1be48bd3 Mon Sep 17 00:00:00 2001 From: Tzafrir Cohen Date: Fri, 13 Feb 2009 21:09:51 +0000 Subject: Rework dahdi_genconf to have separate configuration generation modules. 'dahdi_genconf foo bar' will use the modules Dahdi::Config::Gen::Foo and Dahdi::Config::Gen::Bar to generate configuraion files. Extra formats can thus be added without modifying dahdi_genconf and independently of DAHDI. git-svn-id: http://svn.asterisk.org/svn/dahdi/tools/trunk@6013 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- xpp/perl_modules/Dahdi/Config/Gen.pm | 48 ++++++ xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm | 210 +++++++++++++++++++++++++ xpp/perl_modules/Dahdi/Config/Gen/System.pm | 158 +++++++++++++++++++ xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm | 70 +++++++++ xpp/perl_modules/Dahdi/Config/Gen/Users.pm | 176 +++++++++++++++++++++ 5 files changed, 662 insertions(+) create mode 100644 xpp/perl_modules/Dahdi/Config/Gen.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/System.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm create mode 100644 xpp/perl_modules/Dahdi/Config/Gen/Users.pm (limited to 'xpp/perl_modules') diff --git a/xpp/perl_modules/Dahdi/Config/Gen.pm b/xpp/perl_modules/Dahdi/Config/Gen.pm new file mode 100644 index 0000000..01d602d --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen.pm @@ -0,0 +1,48 @@ +package Dahdi::Config::Gen; +require Exporter; +@ISA = qw(Exporter); + +@EXPORT_OK = qw(is_true); + +use strict; + +sub is_true($) { + my $val = shift || die; + return $val =~ /^(1|y|yes)$/i; +} + +sub show_gconfig($) { + my $gconfig = shift || die; + + print "Global configuration:\n"; + foreach my $key (sort keys %{$gconfig}) { + printf " %-20s %s\n", $key, $gconfig->{$key}; + } +} + +sub bchan_range($) { + my $span = shift || die; + my $first_chan = ($span->chans())[0]; + my $first_num = $first_chan->num(); + my $range_start = $first_num; + my @range; + my $prev = undef; + + die unless $span->is_digital(); + foreach my $c (@{$span->bchan_list()}) { + my $curr = $c + $first_num; + if(!defined($prev)) { + $prev = $curr; + } elsif($curr != $prev + 1) { + push(@range, sprintf("%d-%d", $range_start, $prev)); + $range_start = $curr; + } + $prev = $curr; + } + if($prev >= $first_num) { + push(@range, sprintf("%d-%d", $range_start, $prev)); + } + return join(',', @range); +} + +1; diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm b/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm new file mode 100644 index 0000000..acb74d7 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/Chandahdi.pm @@ -0,0 +1,210 @@ +package Dahdi::Config::Gen::Chandahdi; +use strict; + +use Dahdi::Config::Gen qw(is_true); + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{CHAN_DAHDI_CHANNELS_FILE} || "/etc/asterisk/dahdi-channels.conf"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +# Since chan_dahdi definitions "leak" to the next ones, we try +# To reset some important definitions to their chan_dahdi defaults. +my %chan_dahdi_defaults = ( + context => 'default', + group => '63', # FIXME: should not be needed. + overlapdial => 'no', + busydetect => 'no', + rxgain => 0, + txgain => 0, +); + +sub reset_chandahdi_values { + foreach my $arg (@_) { + if (exists $chan_dahdi_defaults{$arg}) { + print "$arg = $chan_dahdi_defaults{$arg}\n"; + } else { + print "$arg =\n"; + } + } +} + +sub gen_digital($$) { + my $self = shift || die; + my $span = shift || die; + my $gconfig = $self->{GCONFIG}; + my $num = $span->num() || die; + die "Span #$num is analog" unless $span->is_digital(); + if($span->is_pri && $gconfig->{'pri_connection_type'} eq 'R2') { + printf "; Skipped: $gconfig->{'pri_connection_type'}\n\n"; + return; + } + my $type = $span->type() || die "$0: Span #$num -- unkown type\n"; + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $group = $gconfig->{'group'}{"$type"}; + my $context = $gconfig->{'context'}{"$type"}; + my @to_reset = qw/context group/; + + die "$0: missing default group (termtype=$termtype)\n" unless defined($group); + die "$0: missing default context\n" unless $context; + + my $sig = $span->signalling || die "missing signalling info for span #$num type $type"; + grep($gconfig->{'bri_sig_style'} eq $_, 'bri', 'bri_ptmp', 'pri') or die "unknown signalling style for BRI"; + if($span->is_bri() and $gconfig->{'bri_sig_style'} eq 'bri_ptmp') { + $sig .= '_ptmp'; + } + if ($span->is_bri() && $termtype eq 'NT' && is_true($gconfig->{'brint_overlap'})) { + print "overlapdial = yes\n"; + push(@to_reset, qw/overlapdial/); + } + + $group .= "," . (10 + $num); # Invent unique group per span + printf "group=$group\n"; + printf "context=$context\n"; + printf "switchtype = %s\n", $span->switchtype; + printf "signalling = %s\n", $sig; + printf "channel => %s\n", Dahdi::Config::Gen::bchan_range($span); + reset_chandahdi_values(@to_reset); +} + +sub gen_channel($$) { + my $self = shift || die; + my $chan = shift || die; + my $gconfig = $self->{GCONFIG}; + my $type = $chan->type; + my $num = $chan->num; + die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); + my $exten = $gconfig->{'base_exten'} + $num; + my $sig = $gconfig->{'chan_dahdi_signalling'}{$type}; + my $context = $gconfig->{'context'}{$type}; + my $group = $gconfig->{'group'}{$type}; + my $callerid; + my $immediate; + + return if $type eq 'EMPTY'; + die "missing default_chan_dahdi_signalling for chan #$num type $type" unless $sig; + $callerid = ($type eq 'FXO') + ? 'asreceived' + : sprintf "\"Channel %d\" <%04d>", $num, $exten; + if($type eq 'IN') { + $immediate = 'yes'; + } + # FIXME: $immediage should not be set for 'OUT' channels, but meanwhile + # it's better to be compatible with genzaptelconf + $immediate = 'yes' if $gconfig->{'fxs_immediate'} eq 'yes' and $sig =~ /^fxo_/; + my $signalling = $chan->signalling; + $signalling = " " . $signalling if $signalling; + my $info = $chan->info; + $info = " " . $info if $info; + printf ";;; line=\"%d %s%s%s\"\n", $num, $chan->fqn, $signalling, $info; + printf "signalling=$sig\n"; + printf "callerid=$callerid\n"; + printf "mailbox=%04d\n", $exten unless $type eq 'FXO'; + if(defined $group) { + printf "group=$group\n"; + } + printf "context=$context\n"; + printf "immediate=$immediate\n" if defined $immediate; + printf "channel => %d\n", $num; + # Reset following values to default + printf "callerid=\n"; + printf "mailbox=\n" unless $type eq 'FXO'; + if(defined $group) { + printf "group=\n"; + } + printf "context=default\n"; + printf "immediate=no\n" if defined $immediate; + print "\n"; +} + +sub generate($) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + #Dahdi::Config::Gen::show_gconfig($gconfig); + my @spans = @_; + warn "Empty configuration -- no spans\n" unless @spans; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "; Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime); + print <<"HEAD"; +; Dahdi Channels Configurations (chan_dahdi.conf) +; +; This is not intended to be a complete chan_dahdi.conf. Rather, it is intended +; to be #include-d by /etc/chan_dahdi.conf that will include the global settings +; + +HEAD + foreach my $span (@spans) { + printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; + if($span->is_digital()) { + $self->gen_digital($span); + } else { + foreach my $chan ($span->chans()) { + if($genopts->{'freepbx'}) { + # Freepbx has its own idea about channels + my $type = $chan->type; + if($type eq 'FXS' || $type eq 'OUT' || $type eq 'IN') { + printf "; Skip channel=%s($type) -- freepbx option.\n", + $chan->num; + next; + } + } + $self->gen_channel($chan); + } + } + print "\n"; + } + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +chandahdi - Generate configuration for chan_dahdi channels. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Chandahdi; + + my $cfg = new Dahdi::Config::Gen::Chandahdi(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F +This is used as a configuration for asterisk(1). +It should be included in the main F. + +Its location may be overriden via the environment variable +C. + +=head1 OPTIONS + +=over 4 + +=item freepbx + +With this option we do not generate channel definitions for FXS, Input and +Output ports. This is done because these channel definitions need to be +generated and inserted into I database anyway. + +=back diff --git a/xpp/perl_modules/Dahdi/Config/Gen/System.pm b/xpp/perl_modules/Dahdi/Config/Gen/System.pm new file mode 100644 index 0000000..17fb802 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/System.pm @@ -0,0 +1,158 @@ +package Dahdi::Config::Gen::System; +use strict; + +use Dahdi::Config::Gen qw(is_true); + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{DAHDI_CONF_FILE} || "/etc/dahdi/system.conf"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +my $bri_te_last_timing = 1; + +sub gen_digital($$) { + my $gconfig = shift || die; + my $span = shift || die; + my $num = $span->num() || die; + die "Span #$num is analog" unless $span->is_digital(); + my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; + my $timing; + my $lbo = 0; + my $framing = $span->framing() || die "$0: No framing information for span #$num\n"; + my $coding = $span->coding() || die "$0: No coding information for span #$num\n"; + my $span_crc4 = $span->crc4(); + $span_crc4 = (defined $span_crc4) ? ",$span_crc4" : ''; + my $span_yellow = $span->yellow(); + $span_yellow = (defined $span_yellow) ? ",$span_yellow" : ''; + # "MFC/R2 does not normally use CRC4" + # FIXME: a finer way to override: + if ($gconfig->{'pri_connection_type'} eq 'R2') { + $span_crc4 = ''; + $framing = 'cas'; + } + my $dchan_type = 'dchan'; + if ($span->is_bri() && is_true($gconfig->{'bri_hardhdlc'})) { + $dchan_type = 'hardhdlc'; + } + + $timing = ($termtype eq 'NT') ? 0 : $bri_te_last_timing++; + printf "span=%d,%d,%d,%s,%s%s%s\n", + $num, + $timing, + $lbo, + $framing, + $coding, + $span_crc4, + $span_yellow; + printf "# termtype: %s\n", lc($termtype); + if ($gconfig->{'pri_connection_type'} eq 'PRI') { + printf "bchan=%s\n", Dahdi::Config::Gen::bchan_range($span); + my $dchan = $span->dchan(); + printf "$dchan_type=%d\n", $dchan->num(); + } elsif ($gconfig->{'pri_connection_type'} eq 'R2' ) { + my $idle_bits = $gconfig->{'r2_idle_bits'}; + printf "cas=%s:$idle_bits\n", Dahdi::Config::Gen::bchan_range($span); + printf "dchan=%d\n", $span->dchan()->num(); + } +} + +sub gen_signalling($$) { + my $gconfig = shift || die; + my $chan = shift || die; + my $type = $chan->type; + my $num = $chan->num; + + die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); + if($type eq 'EMPTY') { + printf "# channel %d, %s, no module.\n", $num, $chan->fqn; + return; + } + my $signalling = $gconfig->{'dahdi_signalling'}; + my $sig = $signalling->{$type} || die "unknown default dahdi signalling for chan $num type $type"; + if ($type eq 'IN') { + printf "# astbanktype: input\n"; + } elsif ($type eq 'OUT') { + printf "# astbanktype: output\n"; + } + printf "$sig=$num\n"; +} + +sub generate($$$) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + my @spans = @_; + warn "Empty configuration -- no spans\n" unless @spans; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + #Dahdi::Config::Gen::show_gconfig($gconfig); + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "# Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime); + print <<"HEAD"; +# Dahdi Configuration File +# +# This file is parsed by the Dahdi Configurator, dahdi_cfg +# +HEAD + foreach my $span (@spans) { + printf "# Span %d: %s %s\n", $span->num, $span->name, $span->description; + if($span->is_digital()) { + gen_digital($gconfig, $span); + } else { + foreach my $chan ($span->chans()) { + if(1 || !defined $chan->type) { + my $type = $chan->probe_type; + my $num = $chan->num; + die "Failed probing type for channel $num" + unless defined $type; + $chan->type($type); + } + gen_signalling($gconfig, $chan); + } + } + print "\n"; + } + print <<"TAIL"; +# Global data + +loadzone = $gconfig->{'loadzone'} +defaultzone = $gconfig->{'defaultzone'} +TAIL + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +dahdi - Generate configuration for dahdi drivers. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Dahdi; + + my $cfg = new Dahdi::Config::Gen::Dahdi(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F. +This is the configuration for dahdi_cfg(1). + +Its location may be overriden via the environment variable F. diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm b/xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm new file mode 100644 index 0000000..526b62b --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/Unicall.pm @@ -0,0 +1,70 @@ +package Dahdi::Config::Gen::Unicall; +use strict; + +use Dahdi::Config::Gen qw(is_true); + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{UNICALL_CHANNELS_FILE} || "/etc/asterisk/unicall-channels.conf"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +sub generate($) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + #Dahdi::Config::Gen::show_gconfig($gconfig); + my @spans = @_; + warn "Empty configuration -- no spans\n" unless @spans; + die "Only for R2" unless $gconfig->{'pri_connection_type'} eq 'R2'; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "; Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime); + print "; This file should be #included in unicall.conf\n\n"; + foreach my $span (@spans) { + next unless $span->is_digital(); + printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; + my $idle_bits = $gconfig->{'r2_idle_bits'}; + printf "protocolend=%s\n", ($span->termtype() eq 'TE') ? 'cpe' : 'co'; + printf "channel=%s\n", Dahdi::Config::Gen::bchan_range($span); + print "\n"; + } + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +unicall - Generate configuration for unicall channels. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Unicall; + + my $cfg = new Dahdi::Config::Gen::Unicall(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F to be included in +F + +Its location may be overriden via the environment variable +C. diff --git a/xpp/perl_modules/Dahdi/Config/Gen/Users.pm b/xpp/perl_modules/Dahdi/Config/Gen/Users.pm new file mode 100644 index 0000000..7d29a80 --- /dev/null +++ b/xpp/perl_modules/Dahdi/Config/Gen/Users.pm @@ -0,0 +1,176 @@ +package Dahdi::Config::Gen::Users; +use strict; + +use File::Basename; +use Dahdi::Config::Gen qw(is_true); + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{USERS_FILE} || "/etc/asterisk/users.conf"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +sub gen_channel($) { + my $self = shift || die; + my $chan = shift || die; + my $gconfig = $self->{GCONFIG}; + my $type = $chan->type; + my $num = $chan->num; + die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); + my $exten = $gconfig->{'base_exten'} + $num; + my $sig = $gconfig->{'chan_dahdi_signalling'}{$type}; + my $full_name = "$type $num"; + + die "missing default_chan_dahdi_signalling for chan #$num type $type" unless $sig; + print << "EOF"; +[$exten] +callwaiting = yes +context = numberplan-custom-1 +fullname = $full_name +cid_number = $exten +hasagent = no +hasdirectory = no +hasiax = no +hasmanager = no +hassip = no +hasvoicemail = yes +host = dynamic +mailbox = $exten +threewaycalling = yes +vmsecret = 1234 +secret = 1234 +signalling = $sig +dahdichan = $num +registeriax = no +registersip = no +canreinvite = no +nat = no +dtmfmode = rfc2833 +disallow = all +allow = all + +EOF +} + +# generate users.conf . The specific users.conf is strictly oriented +# towards using with the asterisk-gui . +# +# This code could have generated a much simpler and smaller +# configuration file, had there been minimal level of support for +# configuration templates in the asterisk configuration rewriting. Right +# now Asterisk's configuration rewriting simply freaks out in the face +# of templates: http://bugs.digium.com/11442 . +sub generate($) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + #Dahdi::Config::Gen::show_gconfig($gconfig); + my @spans = @_; + warn "Empty configuration -- no spans\n" unless @spans; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + print <<"HEAD"; +;! +;! Automatically generated configuration file +;! Filename: @{[basename($file)]} ($file) +;! Generator: $0 +;! Creation Date: @{[scalar(localtime)]} +;! +[general] +; +; Full name of a user +; +fullname = New User +; +; Starting point of allocation of extensions +; +userbase = @{[$gconfig->{'base_exten'}+1]} +; +; Create voicemail mailbox and use use macro-stdexten +; +hasvoicemail = yes +; +; Set voicemail mailbox @{[$gconfig->{'base_exten'}+1]} password to 1234 +; +vmsecret = 1234 +; +; Create SIP Peer +; +hassip = no +; +; Create IAX friend +; +hasiax = no +; +; Create Agent friend +; +hasagent = no +; +; Create H.323 friend +; +;hash323 = yes +; +; Create manager entry +; +hasmanager = no +; +; Remaining options are not specific to users.conf entries but are general. +; +callwaiting = yes +threewaycalling = yes +callwaitingcallerid = yes +transfer = yes +canpark = yes +cancallforward = yes +callreturn = yes +callgroup = 1 +pickupgroup = 1 +localextenlength = @{[length($gconfig->{'base_exten'})]} + + +HEAD + foreach my $span (@spans) { + next unless grep { $_ eq $span->type} ( 'FXS', 'IN', 'OUT' ); + printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; + foreach my $chan ($span->chans()) { + $self->gen_channel($chan); + } + print "\n"; + } + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +users - Generate configuration for users.conf. + +=head1 SYNOPSIS + + use Dahdi::Config::Gen::Users; + + my $cfg = new Dahdi::Config::Gen::Users(\%global_config, \%genopts); + $cfg->generate(@span_list); + +=head1 DESCRIPTION + +Generate the F which is used by asterisk(1) and AsteriskGUI. + +Its location may be overriden via the environment variable F. -- cgit v1.2.3