#! /usr/bin/perl -w # # Written by Oron Peled # Copyright (C) 2007, Xorcom # This program is free software; you can redistribute and/or # modify it under the same terms as Perl itself. # # $Id:$ # use strict; BEGIN { my $dir = $0; $dir =~ s:/[^/]+$::; unshift(@INC, "$dir", "$dir/zconf"); } use Zaptel; use Zaptel::Xpp; my %default_context = ( FXO => 'from-pstn', FXS => 'from-internal', IN => 'astbank-input', OUT => 'astbank-output' ); my %default_group = ( FXO => '0', FXS => '5', IN => '5', OUT => '5' ); my @zaptel_default_vars = qw( base_exten lc_country context_lines context_phones context_input context_output group_lines group_phones ); my $fxs_immediate = 'no'; my $fxs_default_start; my $lc_country = 'us'; my $loadzone; my $defaultzone; sub map_zaptel_defaults { my %defaults = @_; $default_group{FXO} = $defaults{group_lines} if defined $defaults{group_lines}; $default_group{FXS} = $default_group{IN} = $default_group{OUT} = $defaults{group_phones} if defined $defaults{group_phones}; $default_context{FXO} ||= $defaults{context_lines}; $default_context{FXS} ||= $defaults{context_phones}; $default_context{IN} ||= $defaults{context_input}; $default_context{OUT} ||= $defaults{context_output}; $fxs_immediate ||= $defaults{fxs_immediate}; $fxs_default_start ||= $defaults{fxs_default_start} || 'ls'; $lc_country ||= $defaults{lc_country}; $loadzone = $defaultzone = $lc_country; } my $zapconf_file; my $zapata_file; my @spans = Zaptel::spans(); sub bchan_range($) { my $span = shift || die; my $first_chan = ($span->chans())[0]; my $first_num = $first_chan->num(); my $range; if($span->is_bri()) { $range = sprintf "%d-%d", $first_num, $first_num + 1; } return $range; } sub gen_zaptel_signalling($) { my $chan = shift || die; my $type = $chan->type; my $num = $chan->num; if($type eq 'FXO') { printf "fxsks=%d\n", $num; } elsif($type eq 'FXS') { printf "fxo%s=%d\n", $fxs_default_start, $num; } elsif ($type eq 'IN') { printf "# astbanktype: input\n"; printf "fxo%s=%d\n", $fxs_default_start, $num; } elsif ($type eq 'OUT') { printf "# astbanktype: output\n"; printf "fxo%s=%d\n", $fxs_default_start, $num; } elsif ($type eq 'BRI_TE') { printf "# termtype: te\n"; } elsif ($type eq 'BRI_NT') { printf "# termtype: nt\n"; } elsif($type eq 'EMPTY') { printf "# channel %d, %s, no module.\n", $num, $chan->fqn; return; } } my $bri_te_last_timing = 1; sub gen_zaptel_digital($) { my $span = shift || die; my $num = $span->num(); my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; my $timing; my $lbo = 1; 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_yellow = $span->yellow(); $span_yellow = (defined $span_yellow) ? ",$span_yellow" : ''; $timing = ($termtype eq 'NT') ? 0 : $bri_te_last_timing++; printf "span=%d,%d,%d,%s,%s\n", $num, $timing, $lbo, $framing, "$coding$span_yellow"; printf "# termtype: %s\n", lc($termtype); printf "bchan=%s\n", bchan_range($span); my $dchan = $span->dchan(); printf "dchan=%d\n", $dchan->num(); } sub gen_zaptelconf($) { my $file = shift || die; rename "$file", "$file.bak" or $!{ENOENT} or die "Failed to backup old config: $!\n"; 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"; # Zaptel Configuration File # # This file is parsed by the Zaptel Configurator, ztcfg # HEAD foreach my $span (@spans) { printf "# Span %d: %s %s\n", $span->num, $span->name, $span->description; if($span->is_bri()) { gen_zaptel_digital($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_zaptel_signalling($chan); } } print "\n"; } print <<"TAIL"; # Global data loadzone = $loadzone defaultzone = $defaultzone TAIL close F; select $old; } sub gen_zapata_channel($) { my $chan = shift || die; my $type = $chan->type; my $num = $chan->num; my $sig; my $immediate; my $callerid = sprintf "\"Channel %d\" <4%03d>", $num, $num; my $context = $default_context{$type}; my $group = $default_group{$type}; if ($type eq 'FXO') { $sig = "fxs_ks"; $callerid = 'asreceived'; } elsif($type eq 'FXS') { $sig = "fxo_" . $fxs_default_start; $immediate = 'yes' if $fxs_immediate eq 'yes'; } elsif($type eq 'IN') { $sig = "fxo_" . $fxs_default_start; $immediate = 'yes'; } elsif($type eq 'OUT') { $sig = "fxo_" . $fxs_default_start; } elsif($type eq 'EMPTY') { return; } die "Unknown signalling for channel $num type $type\n" unless defined $sig; printf ";;; line=\"%d %s\"\n", $num, $chan->fqn; printf "signalling=$sig\n"; printf "callerid=$callerid\n"; printf "mailbox=4%03d\n", $num unless $type eq 'FXO'; if(defined $group) { printf "group=%d\n", $group; } 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 gen_zapataconf($) { my $file = shift || die; rename "$file", "$file.bak" or $!{ENOENT} or die "Failed to backup old config: $!\n"; 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"; ; Zaptel Channels Configurations (zapata.conf) ; ; This is not intended to be a complete zapata.conf. Rather, it is intended ; to be #include-d by /etc/zapata.conf that will include the global settings ; HEAD foreach my $span (@spans) { printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; foreach my $chan ($span->chans()) { gen_zapata_channel($chan); } print "\n"; } close F; select $old; } # Use the shell to source a file and expand a given list # of variables. sub do_source($@) { my $file = shift; my @vars = @_; my @output = `env -i sh -e -c '. $file; export @vars; env'`; die "$0: Sourcing '$file' exited with $?" if $?; my %vars; foreach my $line (@output) { chomp $line; my ($k, $v) = split(/=/, $line, 2); $vars{$k} = $v if grep /^$k$/, @vars; } return %vars; } sub set_defaults { my $zaptel_boot_debian = $ENV{ZAPTEL_BOOT_DEBIAN} || "/etc/default/zaptel"; my $zaptel_boot_fedora = $ENV{ZAPTEL_BOOT_FEDORA} || "/etc/sysconfig/zaptel"; # Source default files my %source_defaults; foreach my $defaults ($zaptel_boot_debian, $zaptel_boot_fedora) { %source_defaults = do_source($defaults, @zaptel_default_vars) if -r $defaults; } map_zaptel_defaults(%source_defaults); $zapconf_file = $ENV{ZAPCONF_FILE} || "/etc/zaptel.conf"; $zapata_file = $ENV{ZAPATA_FILE} || "/etc/asterisk/zapata-channels.conf"; } set_defaults; gen_zaptelconf $zapconf_file; gen_zapataconf $zapata_file; __END__ =head1 NAME zapconf - Generate configuration for zaptel channels. =head1 SYNOPSIS zapconf =head1 DESCRIPTION