实现cdr实时发送 通话信息的代码
makefile 文件
#
# Makefile for Asterisk applications
#
# Copyright (C) 2007-2008, Francois Aucamp
#
# Francois Aucamp <faucamp@csir.co.za>
#
# This program is free software, distributed under the terms of
# the GNU General Public License
#
#
# Some metadata about this module
#
NAME=cdr_es
VERSION=0.3
#
# System's lib directory, guessed from the processor type.
# This is used my ASTERISKMODDIR, below
#
LIBDIR=/usr/lib$(shell if uname -m | grep -q 64; then echo "64"; fi)
#
# Set the ASTERISKMODDIR variable to the directory where ASTERISK's modules reside.
# The modules will be installed in this directory.
#
ASTERISKMODDIR=$(LIBDIR)/asterisk/modules
#
# Set the ASTERISKETCDIR variable to the directory where ASTERISK's configuration
# files reside. The config files will be installed in this directory.
#
ASTERISKETCDIR=/etc/asterisk
#
# Set the ASTERISKVERSION variable to the version of Asterisk you are compiling
# for. This can be 1.0, 1.2 or 1.4
#
ASTERISKVERSION=1.4
# Set ASTERISKINCLUDE if you have non-standard locations for your header files
INCLUDE=$(ASTERISKINCLUDE) #/usr/include/asterisk
# Asterisk executable
ASTERISKBIN=/sbin/asterisk
# List of modules to build
APPS=cdr_es.so
CC=gcc
INSTALL=install
OPTIMIZE=-O2
#Include debug symbols in the executables (-g)
DEBUG=-g
DEFINES=-D_REENTRANT -D_GNU_SOURCE
ifeq ($(ASTERISKVERSION),1.2)
DEFINES+=-DASTERISK_VERSION=2
endif
ifeq ($(ASTERISKVERSION),1.0)
DEFINES+=-DASTERISK_VERSION=0
endif
CFLAGS+=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(OPTIMIZE)
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
CFLAGS+=-fPIC
LIBS+=-lm
all: $(APPS)
clean:
rm -f *.so *.o look .depend
%.so : %.o
$(CC) $(SOLINK) -o $@ $<
cdr_es.o: cdr_es.c
$(CC) $(INCLUDE) $(CFLAGS) $(DEFINES) -c -o cdr_es.o cdr_es.c
cdr_es.so: cdr_es.o
$(CC) -shared -Xlinker -x -o $@ $< $(LIBS)
install: all
@if [ -d $(ASTERISKMODDIR) ]; then /
for x in $(APPS); do echo $(INSTALL) -m 755 $$x $(DESTDIR)$(ASTERISKMODDIR); $(INSTALL) -m 755 $$x $(DESTDIR)$(ASTERISKMODDIR); done /
else /
echo; echo $(ASTERISKMODDIR) does not exist.; /
echo Please set ASTERISKMODDIR to the directory containing your Asterisk modules.; /
echo e.g. make install ASTERISKMODDIR=/your/directory/here; /
exit 1; /
fi
@echo; echo Installation successful.;
reload: install
$(ASTERISKBIN) -rx "unload ${APPS}"
$(ASTERISKBIN) -rx "load ${APPS}"
sdist:
mkdir $(NAME)-$(VERSION)
cp -pf .cproject .project asterisk-cdr_es.spec AUTHORS ChangeLog COPYING Makefile README cdr_es.c $(NAME)-$(VERSION)
tar -zcvf $(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION)
rm -rf $(NAME)-$(VERSION)
cdr_es.spec 文件
Name: asterisk-cdr_es
Version: 0.3
Release: 1%{?dist}
Summary: AGI Audio File Transfer Addons for Asterisk
Group: Applications/Internet
License: GPL
URL: http://agi-audiotx.sourceforge.net
Source0: http://kent.dl.sourceforge.net/sourceforge/agi-audiotx/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: asterisk-devel
Requires: asterisk
%description
AGI Audio File Transfer Addons for Asterisk - this is a module for Asterisk
that extends Asterisk's AGI interface by adding commands that allow the
transfer of audio files to and from Asterisk via the AGI session.
Very useful for FastAGI connections when recording audio or playing remote
pre-recorded audio prompts.
%prep
%setup -q
%build
make %{?_smp_mflags} CFLAGS="$RPM_OPT_FLAGS"
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT%{_libdir}/asterisk/modules
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/asterisk
make install DESTDIR=$RPM_BUILD_ROOT
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%doc AUTHORS ChangeLog COPYING README
%{_libdir}/asterisk/modules/cdr_es.so
%changelog
* Tue Feb 12 2008 Francois Aucamp <faucamp@csir.co.za> - 0.3-1
- Initial RPM build for Asterisk 1.4
主要代码: cdr_es.c
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* Includes code and algorithms from the Zapata library.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
// 必须定义 make 才可以编译 否则找不到报错
#define AST_MODULE "cdr_es"
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 70841 $")
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/pbx.h"
#include "asterisk/logger.h"
#include "asterisk/utils.h"
#define DATE_FORMAT "%Y-%m-%d %T"
typedef enum
{
ETypeCOM = 0,
ETypeTCP,
ETypeUDP,
}ECdrType;
typedef struct
{
short m_sCallState; //=1:answered; <>1:no answered
char m_acDate[9];
char m_acStartTm[7];
char m_acAnswerTm[7];
char m_acEndTm[7];
char m_acCerNum[18];
char m_acCedNum[18];
}ECdrFormat;
AST_MUTEX_DEFINE_STATIC(lock);
static char *name = "cdr-escene";
static char format[1024]="";
static int g_iFd = -1;
static ECdrType g_iType;
static int g_iComNum;
static int g_iBaudRate;
static char g_acServerIp[20];
static unsigned short g_sPort;
void set_speed(int fd, int speed);
int set_Parity(int fd, int databits, int stopbits, int parity);
int Cdr2Buff( ECdrFormat *pFormat, char *pBuff, int iLen );
int TcpConnect();
int CdrBackup( char *pInfo );
static int load_config(int reload)
{
struct ast_config *cfg;
struct ast_variable *var;
int res = -1;
const char *pInfo;
strcpy(format, "");
ast_mutex_lock(&lock);
if((cfg = ast_config_load("cdr_escene.conf")))
{
var = ast_variable_browse(cfg, "mappings");
while(var)
{
if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value))
{
if (strlen(var->value) > (sizeof(format) - 1))
ast_log(LOG_WARNING, "Format string too long, will be truncated, at line %d/n", var->lineno);
ast_copy_string(format, var->value, sizeof(format) - 1);
strcat(format,"/n");
if (var->next)
{
ast_log(LOG_NOTICE, "Sorry, only one mapping is supported, mapping '%s' will be ignored./n",
var->next->name );
break;
}
}
else
ast_log(LOG_NOTICE, "Mapping must have both filename and format at line %d/n", var->lineno);
var = var->next;
}
if ((pInfo = ast_variable_retrieve(cfg, "settings", "Type")) != NULL)
{
if (strcmp(pInfo, "COM") == 0)
{
g_iType = ETypeCOM;
pInfo = ast_variable_retrieve( cfg, "settings", "ComNum" );
if (pInfo)
{
if (sscanf(pInfo, "%d", &g_iComNum ) < 1)
{
ast_log( LOG_WARNING, "Get comNum can't convert %s/n", pInfo );
g_iComNum = 1;
}
}
else
g_iComNum = 1;
pInfo = ast_variable_retrieve( cfg, "settings", "BaudRate" );
if (pInfo)
{
if (sscanf(pInfo, "%d", &g_iBaudRate ) < 1)
{
ast_log( LOG_WARNING, "Get BaudRate can't convert %s/n", pInfo );
g_iBaudRate = 9600;
}
}
else
g_iBaudRate = 9600;
ast_log( LOG_NOTICE, "CDR setting: type=%d, ComNum=%d, BaudRate=%d/n", g_iType, g_iComNum, g_iBaudRate );
}
else
{
if (strcmp(pInfo, "TCP") == 0)
g_iType = ETypeTCP;
else if (strcmp(pInfo, "UDP") == 0)
g_iType = ETypeUDP;
else
{
ast_log( LOG_ERROR, "Get unsupport type:%s, cdr to back file/n", pInfo );
}
pInfo = ast_variable_retrieve( cfg, "settings", "ServerIp" );
if (!pInfo)
{
ast_log( LOG_ERROR, "No ServerIp is set, cdr to back file/n");
}
strncpy( g_acServerIp, pInfo, sizeof(g_acServerIp)-1 );
pInfo = ast_variable_retrieve( cfg, "settings", "ServerPort" );
if (!pInfo)
{
ast_log( LOG_ERROR, "No ServerPort is set, cdr to back file/n");
}
g_sPort = strtol( pInfo, 0, 0 );
ast_log( LOG_NOTICE, "CDR setting: type=%d, ip=%s, port=%d/n", g_iType, g_acServerIp, g_sPort );
}
}
else
{
ast_log(LOG_WARNING, "Can't get settings, cdr to back file/n" );
}
ast_config_destroy(cfg);
res = 0;
if (g_iType == ETypeCOM)
{
char acComName[32];
sprintf( acComName, "/dev/ttyS%d", g_iComNum-1 );
g_iFd = open( acComName, O_RDWR);
if (g_iFd <= 0)
{
ast_log( LOG_WARNING, "Fail to open %s./n", acComName );
}
if (set_Parity(g_iFd, 8, 1, 's') < 0)
{
ast_log( LOG_WARNING, "Fails with set_Parity./n");
close( g_iFd );
g_iFd = -1;
}
set_speed( g_iFd, g_iBaudRate );
}
else if (g_iType == ETypeUDP)
{
g_iFd = socket( AF_INET, SOCK_DGRAM, 0 );
if (g_iFd <= 0)
{
ast_log( LOG_WARNING, "CDR of UDP fails with socket, err:'%s'./n", strerror(errno) );
}
}
else if (g_iType == ETypeTCP)
{
if (TcpConnect() < 0)
{
close( g_iFd );
g_iFd = -1;
return -1;
}
}
}
else
{
if (reload)
ast_log(LOG_WARNING, "Failed to reload configuration file./n");
else
ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated./n");
}
ast_mutex_unlock(&lock);
return res;
}
static int custom_log(struct ast_cdr *cdr)
{
/* Make sure we have a big enough buf */
char buf[128];
int iLen;
ECdrFormat oFormat;
struct tm oTm, *pTm;
if (cdr == 0)
{
ast_log( LOG_WARNING, "cdr_es write with cdr==NULL/n");
return -1;
}
memset(buf, 0 , sizeof(buf));
memset( &oFormat, 0, sizeof(oFormat) );
strncpy( oFormat.m_acCerNum, cdr->src, 17 );
strncpy( oFormat.m_acCedNum, cdr->dst, 17 );
/*
localtime_r( &cdr->start.tv_sec, &oTm );
sprintf( oFormat.m_acDate, "%04d%02d%02d", oTm.tm_year, oTm.tm_mon, oTm.tm_mday );
sprintf( oFormat.m_acStartTm, "%02d%02d%02d", oTm.tm_hour, oTm.tm_min, oTm.tm_sec );
if (cdr->answer.tv_sec > 0)
{
oFormat.m_sCallState = 1;
localtime_r( &cdr->answer.tv_sec, &oTm );
sprintf( oFormat.m_acAnswerTm, "%02d%02d%02d", oTm.tm_hour, oTm.tm_min, oTm.tm_sec );
}
localtime_r( &cdr->end.tv_sec, &oTm );
sprintf( oFormat.m_acEndTm, "%02d%02d%02d", oTm.tm_hour, oTm.tm_min, oTm.tm_sec );
*/
pTm = localtime( (time_t*)&cdr->start.tv_sec );
sprintf( oFormat.m_acDate, "%04d%02d%02d", pTm->tm_year+1900, pTm->tm_mon+1, pTm->tm_mday );
sprintf( oFormat.m_acStartTm, "%02d%02d%02d", pTm->tm_hour, pTm->tm_min, pTm->tm_sec );
if (cdr->answer.tv_sec > 0)
{
oFormat.m_sCallState = 1;
pTm = localtime( (time_t*)&cdr->answer.tv_sec );
sprintf( oFormat.m_acAnswerTm, "%02d%02d%02d", pTm->tm_hour, pTm->tm_min, pTm->tm_sec );
}
else
strcpy( oFormat.m_acAnswerTm, "------" );
pTm = localtime( (time_t*)&cdr->end.tv_sec );
sprintf( oFormat.m_acEndTm, "%02d%02d%02d", pTm->tm_hour, pTm->tm_min, pTm->tm_sec );
Cdr2Buff( &oFormat, buf, 80 );
if (g_iType == ETypeCOM)
{
iLen = write( g_iFd, buf, strlen(buf) );
ast_log( LOG_NOTICE, "cdr-es send serial-%d(%d):%s./n", g_iComNum, iLen, buf );
}
else if (g_iType == ETypeTCP)
{
if (g_iFd >= 0)
{
iLen = send( g_iFd, buf, strlen(buf), 0 );
if (iLen <= 0)
{
ast_log( LOG_WARNING, "Send CDR fails with err:'%s'./n", strerror(errno) );
if (TcpConnect() >= 0)
send( g_iFd, buf, strlen(buf), 0 );
else
CdrBackup( buf );
}
else
ast_log( LOG_NOTICE, "cdr-es send tcp %s:%d cdr:%s/n", g_acServerIp, g_sPort, buf );
}
else
{
if (TcpConnect() >= 0)
send( g_iFd, buf, strlen(buf), 0 );
else
CdrBackup( buf );
}
}
else if (g_iType == ETypeUDP)
{
struct sockaddr_in oAddr;
oAddr.sin_family = AF_INET;
oAddr.sin_port = htons( g_sPort );
inet_aton( g_acServerIp, &oAddr.sin_addr );
iLen = sendto( g_iFd, buf, strlen(buf), 0, (struct sockaddr*)&oAddr, sizeof(oAddr) );
if (iLen <= 0)
{
ast_log( LOG_WARNING, "Sendto CDR fails with err:'%s'./n", strerror(errno) );
CdrBackup( buf );
}
else
{
ast_log( LOG_NOTICE, "cdr-es send udp %s:%d cdr:%s/n", g_acServerIp, g_sPort, buf );
}
}
return 0;
}
static int unload_module(void)
{
ast_cdr_unregister(name);
return 0;
}
static int load_module(void)
{
int res = 0;
if (!load_config(0))
{
// custom_log函数 每次CDR post 时将会调用 当你挂电话,将会看到CDR 处理被执行 custom_log函数的行为
res = ast_cdr_register(name, ast_module_info->description, custom_log);
if (res)
ast_log(LOG_ERROR, "Unable to register custom CDR handling/n");
return res;
}
else
return AST_MODULE_LOAD_DECLINE;
}
static int reload(void)
{
return load_config(1);
}
//最初 cdr_es模块注册了load_module()函数作为asterisk在加载本模块时的入口函数 AST_MODULE_INFO。
// .load = load_module, 结构体的赋植 形式
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Customizable Comma Separated Values CDR Backend",
.load = load_module,
.unload = unload_module,
.reload = reload,
);
/*functions for operate serial programming*/
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,
19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed)
{
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
{
perror("tcsetattr fd1");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
}
int set_Parity(int fd, int databits, int stopbits, int parity)
{
struct termios options;
if (tcgetattr( fd,&options) != 0)
{
perror("SetupSerial 1");
return -1;
}
options.c_cflag &= ~CSIZE;
switch (databits) /*设置数据位数*/
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size/n");
return -1;
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity/n");
return -1;
}
/* 设置停止位*/
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits/n");
return -1;
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/
options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
options.c_oflag &= ~OPOST; /*Output*/
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("SetupSerial 3");
return -1;
}
return 0;
}
int Cdr2Buff( ECdrFormat *pFormat, char *pBuff, int iLen )
{
int iPos = 0, iTmpLen;
if (iLen < 76)
return -1;
if (pFormat==0 || pBuff==0 )
return -1;
memset( pBuff, 0, iLen );
strcpy( pBuff, "0000" );
strcat( pBuff, " " );
iPos += 5;
sprintf( pBuff+iPos, "%02d", pFormat->m_sCallState );
strcat( pBuff, " " );
iPos += 3;
strncpy( pBuff+iPos, pFormat->m_acDate, 8 );
strcat( pBuff, " " );
iPos += 9;
strncpy( pBuff+iPos, pFormat->m_acStartTm, 6 );
strcat( pBuff, " " );
iPos += 7;
strncpy( pBuff+iPos, pFormat->m_acAnswerTm, 6 );
strcat( pBuff, " " );
iPos += 7;
strncpy( pBuff+iPos, pFormat->m_acEndTm, 6 );
strcat( pBuff, " " );
iPos += 7;
strncpy( pBuff+iPos, pFormat->m_acCerNum, 18 );
if ((iTmpLen=strlen(pFormat->m_acCerNum)) < 18)
{
memset( pBuff+iPos+iTmpLen, '-', 18-iTmpLen );
}
strcat( pBuff, " " );
iPos += 19;
strncpy( pBuff+iPos, pFormat->m_acCedNum, 18 );
if ((iTmpLen=strlen(pFormat->m_acCedNum)) < 18)
{
memset( pBuff+iPos+iTmpLen, '-', 18-iTmpLen );
}
strcat( pBuff, "/n" );
return 0;
}
int TcpConnect()
{
struct sockaddr_in oAddr;
int iFlags;
struct pollfd oFd[1];
if (g_iFd >= 0)
close( g_iFd );
g_iFd = socket( AF_INET, SOCK_STREAM, 0 );
if (g_iFd < 0)
{
ast_log( LOG_WARNING, "CDR of TCP fails with socket, err:'%s'./n", strerror(errno) );
return -1;
}
oAddr.sin_family = AF_INET;
oAddr.sin_port = htons( g_sPort );
inet_aton( g_acServerIp, &oAddr.sin_addr );
/*
iFlags = fcntl( g_iFd, F_GETFL );
fcntl( g_iFd, F_SETFL, iFlags|O_NONBLOCK);
connect( g_iFd, (struct sockaddr*)&oAddr, sizeof(oAddr) );
oFd[0].fd = g_iFd;
oFd[0].events = POLLIN;
iFlags = poll( oFd, 1, 1000 );
if (iFlags <= 0)
{
ast_log( LOG_WARNING, "CDR of TCP fails with poll and refuse to work./n");
close( g_iFd );
g_iFd = -1;
}
*/
if (connect(g_iFd, (struct sockaddr*)&oAddr, sizeof(oAddr)) < 0)
{
ast_log( LOG_WARNING, "CDR of TCP connect svr<%s:%d> err:'%s'./n", g_acServerIp, g_sPort, strerror(errno) );
close( g_iFd );
g_iFd = -1;
return -1;
}
ast_log( LOG_NOTICE, "CDR of TCP connect svr<%s:%d> ok./n", g_acServerIp, g_sPort);
return 0;
}
int CdrBackup( char *pInfo )
{
int iFd;
if (pInfo == 0)
return -1;
iFd = open( "/var/log/asterisk/cdr-escene/Master.csv", O_WRONLY|O_APPEND|O_CREAT );
if (iFd >= 0)
{
write( iFd, pInfo, strlen(pInfo) );
close( iFd );
ast_log( LOG_NOTICE, "Back cdr to /var/log/asterisk/cdr-escene/Master.csv/n" );
}
else
ast_log( LOG_WARNING, "Can't open backfile:/var/log/asterisk/cdr-escene/Master.csv, err:%s/n", strerror(errno) );
return 0;
}
(注: cdr_escene.conf 在/etc/asterisk 目录
其内容是在web界面生成的 大致内容是 csv :内容 及 传输方式 (udp tcp com) ip 端口)
cd /asterisk1.4.0 (asterisk 源代码位置)
mkdir cdr_es
把上面三个文件 放一起 然后执行 make命令 就会生成 cdr_es.so模块
如果 不重新启动系统 就在asterisk 命令行重新 load cdr_es.so 把这模块启动
如果 你写agi命令 你就可以 用 show agi 就可以找到你写的命令
附asterisk 外挂程序 可以参考: http://agi-audiotx.sourceforge.net/
如果 不重新启动系统 就在asterisk 命令行重新 agi-audiotx.so 把这模块启动
如果 你写agi命令 你就可以 用 show agi 就可以找到你写的命令(agi命令 在phpagi.php(添加)修改下就可以php调用来编程了)
isexisting soundfile Is existing Sound File
get soundfile Get Sound File
put soundfile Put Sound File
Asterisk 可加载模块
app_adsiprog.so => (Asterisk ADSI Programming Application)
——用于支持模拟显示服务接口的终端设备,在终端屏幕上操作菜单等。
app_amd.so => (Answering Machine Detection Application)
——用于外呼时终端应答状态检测
app_authenticate.so => (Authentication Application)
——Asterisk用户认证,以文本形式存储用户密码
app_cdr.so => (Tell Asterisk to not maintain a CDR for the current call)
——通知Asterisk不用为当前通话维护通话详单记录表
app_chanisavail.so => (Check channel availability)
——检查通道状态是否可用
app_channelredirect.so => (Channel Redirect)
——重定向给定通道到拨号目标
app_chanspy.so => (Listen to the audio of an active channel)
——监听通话通道
app_controlplayback.so => (Control Playback Application)
——控制语音播放,快进快退停止等
app_db.so => (Database Access Functions)
——访问Asterisk自有数据库
app_dial.so => (Dialing Application)
——拨号应用
app_dictate.so => (Virtual Dictation Machine)
——应用于可控菜单录音
app_directed_pickup.so => (Directed Call Pickup Application)
——用A电话去接听正在振铃的B
app_directory.so => (Extension Directory)
——Extension目录服务
app_disa.so => (DISA (Direct Inward System Access) Application)
——直接呼入服务应用
app_dumpchan.so => (Dump Info About The Calling Channel)
——呼叫通道的日志记录
app_echo.so => (Simple Echo Application)
——简单Echo应用
app_exec.so => (Executes dialplan applications)
——执行拨号应用命令
app_externalivr.so => (External IVR Interface Application)
——外部IVR接口应用
app_flash.so => (Flash channel application)
——闪接通道应用
app_forkcdr.so => (Fork The CDR into 2 separate entities)
——分离详单为2个不同的实体
app_getcpeid.so => (Get ADSI CPE ID)
——获得ADSI(模拟显示服务)终端设备ID
app_hasnewvoicemail.so => (Indicator for whether a voice mailbox has messages in a given folder.)
——提示给定的目录中语音邮箱是否有消息
app_ices.so => (Encode and Stream via icecast and ices)
——采用icecast和ices方式编码语音流
app_image.so => (Image Transmission Application)
——图像传输应用
app_lookupblacklist.so => (Look up Caller*ID name/number from blacklist database)
——从黑名单数据库中查找主叫名字和号码
app_lookupcidname.so => (Look up CallerID Name from local database)
——从本地数据库中查找主叫名字
app_macro.so => (Extension Macros)
——执行宏命令
app_meetme.so => (MeetMe conference bridge)
——桥接会议
app_milliwatt.so => (Digital Milliwatt (mu-law) Test Application)
——产生毫瓦级常数用于测量应用
app_mixmonitor.so => (Mixed Audio Monitoring Application)
——混合音频监控应用
app_morsecode.so => (Morse code)
——莫尔斯编码
app_mp3.so => (Silly MP3 Application)
——无聊的MP3应用
app_nbscat.so => (Silly NBS Stream Application)
——无聊的NBS流应用
app_page.so => (Page Multiple Phones)
——群呼
app_parkandannounce.so => (Call Parking and Announce Application)
——呼叫停泊和引导词应用
app_playback.so => (Sound File Playback Application)
——放音引用
app_privacy.so => (Require phone number to be entered
——需要号码输入
app_random.so => (Random goto)
——随机跳转
app_read.so => (Read Variable Application)
——读取变量应用
app_readfile.so => (Stores output of file into a variable)
——把文件输出存放在变量中(读文件内容)
app_realtime.so => (Realtime Data Lookup/Rewrite)
——实时数据查找重写
app_record.so => (Trivial Record Application)
——价值不高的录音应用
app_sayunixtime.so => (Say time)
——读出系统时间
app_senddtmf.so => (Send DTMF digits Application)
——发送DTMF数字应用
app_sendtext.so => (Send Text Applications)
——发送文本应用
app_setcallerid.so => (Set CallerID Application)
——设置主叫号码应用
app_setcdruserfield.so => (CDR user field apps)
——设置通话详单用户自定义字段
app_settransfercapability.so => (Set ISDN Transfer Capability)
——设置ISDN呼叫转接能力
app_sms.so => (SMS/PSTN handler)
——短信/电话网 处理机
app_softhangup.so => (Hangs up the requested channel)
——软挂机
app_speech_utils.so => (Dialplan Speech Applications)
——拨号方案中的语音演讲应用
app_stack.so => (Stack Routines)
——常规堆栈
app_system.so => (Generic System() application)
——系统应用
app_talkdetect.so => (Playback with Talk Detection)
——放音时进行声音检测(如:检测真人说话)
app_test.so => (Interface Test Application)
——接口测试应用
app_transfer.so => (Transfer)
——呼叫转接服务
app_url.so => (Send URL Applications)
——发送URL应用
app_userevent.so => (Custom User Event Application)
——自定义用户事件
app_verbose.so => (Send verbose output)
——发送控制台输出信息
app_voicemail.so => (Comedian Mail (Voicemail System))
——语音邮件系统
app_waitforring.so => (Waits until first ring after time)
——振铃等待
app_waitforsilence.so => (Wait For Silence)
——静默等待
app_while.so => (While Loops and Conditional Execution)
——循环条件执行
app_zapateller.so => (Block Telemarketers with Special Information Tone)
——用特殊振铃音阻止电话营销阻
app_zapbarge.so => (Barge in on Zap channel application)
——载入Zap通道应用
app_zapras.so => (Zap RAS Application)
——zap 远程访问服务
app_zapscan.so => (Scan Zap channels application)
——Zap通道扫描应用
cdr_custom.so => (Customizable Comma Separated Values CDR Backend)
——用逗号分割的自定义CDR条目
cdr_manager.so => (Asterisk Manager Interface CDR Backend)
——Asterisk管理接口
chan_features.so => (Feature Proxy Channel)
——特征代理通道
chan_iax2.so => (Inter Asterisk eXchange (Ver 2))
——支持IAX2
chan_local.so => (Local Proxy Channel)
——本地虚拟通道
chan_mgcp.so => (Media Gateway Control Protocol (MGCP))
——媒体网关控制协议
chan_sip.so => (Session Initiation Protocol (SIP))
——SIP协议支持
chan_usbradio.so => (channel driver for USB sound fobs and Asterisk cmd Rpt)
——usb通道驱动
chan_zap.so => (Zapata Telephony)
——Zap卡支持
codec_a_mu.so => (A-law and Mulaw direct Coder/Decoder)
——a-law和mulaw编解码支持
codec_adpcm.so => (Adaptive Differential PCM Coder/Decoder)
——pcm编解码
codec_alaw.so => (A-law Coder/Decoder)
——a-law编解码
codec_g726.so => (ITU G.726-32kbps G726 Transcoder)
——G726编码传输
codec_gsm.so => (GSM Coder/Decoder)
——GSM编码支持
codec_ilbc.so => (iLBC Coder/Decoder)
——iLBC编解码
codec_lpc10.so => (LPC10 2.4kbps Coder/Decoder)
——LPC10编解码
codec_ulaw.so => (mu-Law Coder/Decoder)
——mu-law编解码
codec_zap.so => (Generic Zaptel Transcoder Codec Translator)
——Zaptel编解码转换
format_g723.so => (G.723.1 Simple Timestamp File Format)
format_g726.so => (Raw G.726 (16/24/32/40kbps) data)
format_g729.so => (Raw G729 data)
format_gsm.so => (Raw GSM data)
format_h263.so => (Raw H.263 data)
format_h264.so => (Raw H.264 data)
format_ilbc.so => (Raw iLBC data)
format_jpeg.so => (JPEG (Joint Picture Experts Group) Image Format)
format_pcm.so => (Raw/Sun uLaw/ALaw 8KHz Audio support (PCM
format_sln.so => (Raw Signed Linear Audio support (SLN))
format_vox.so => (Dialogic VOX (ADPCM) File Format)
format_wav.so => (Microsoft WAV format (8000Hz Signed Linear))
format_wav_gsm.so => (Microsoft WAV format (Proprietary GSM))
func_base64.so => (base64 encode/decode dialplan functions)
——base64编解码拨号方案函数
func_callerid.so => (Caller ID related dialplan function)
——主叫相关拨号方案函数
func_cdr.so => (CDR dialplan function)
——CDR拨号方案函数
func_channel.so => (Channel information dialplan function)
——通道信息拨号方案函数
func_cut.so => (Cut out information from a string)
——从字符串剪切相关信息
func_db.so => (Database (astdb) related dialplan functions)
——Astdb相关拨号方案函数
func_enum.so => (ENUM related dialplan functions)
——ENUM(电话号码映射telephone number mapping working group)相关拨号函数
func_env.so => (Environment/filesystem dialplan functions)
——环境/文件系统拨号方案函数
func_global.so => (Global variable dialplan functions)
——全局变量
func_groupcount.so => (Channel group dialplan functions)
——通道组
func_language.so => (Channel language dialplan function)
——通道语言种类
func_logic.so => (Logical dialplan functions)
——逻辑拨号方案函数
func_math.so => (Mathematical dialplan function)
——精确拨号方案函数
func_md5.so => (MD5 digest dialplan functions)
——MD5 拨号方案函数
func_moh.so => (Music-on-hold dialplan function)
——音乐保持拨号方案函数
func_rand.so => (Random number dialplan function)
——产生随机数
func_realtime.so => (Read/Write values from a RealTime repository)
——RealTime实时读写
func_sha1.so => (SHA-1 computation dialplan function)
——SHA-1算法
func_strings.so => (String handling dialplan functions)
——字符串处理
func_timeout.so => (Channel timeout dialplan functions)
——通道超时
func_uri.so => (URI encode/decode dialplan functions)
——URI编解码
pbx_config.so => (Text Extension Configuration)
——文本Extension配置
pbx_loopback.so => (Loopback Switch)
——环回交换
pbx_realtime.so => (Realtime Switch)
——Realltime交换
pbx_spool.so => (Outgoing Spool Support)
——外呼队列支持
res_adsi.so => (ADSI Resource (not optional))
——ADSI(模拟显示服务接口)资源,没有选项
res_agi.so => (Asterisk Gateway Interface (AGI))
——AGI接口
res_clioriginate.so => (Call origination from the CLI)
——从CLI发起呼叫
res_convert.so => (File format conversion CLI command)
——CLI文件格式转换命令
res_crypto.so => (Cryptographic Digital Signatures)
——加密数字签名
res_features.so => (Call Features Resource)
——呼叫特征资源
res_indications.so => (Indications Resource)
——显示资源
res_monitor.so => (Call Monitoring Resource)
——呼叫监控
res_musiconhold.so => (Music On Hold Resource)
——音乐保持资源
res_speech.so => (Generic Speech Recognition API)
——语音识别接口
/etc/asterisk/phpagi.conf 配置内容:
[phpagi]
debug=true //是否打开debug,一般生产环境关闭
error_handler=true
tempdir=/var/spool/asterisk/tmp/
[asmanager]
server=10.1.0.7
port=5038
username=astman
secret=astman
[fastagi]
setuid=true
basedir=/var/lib/asterisk/agi-bin/