asterisk 外挂程序 及 Asterisk 可加载模块 及 phpagi.conf 配置内容

2024-02-26 12:08

本文主要是介绍asterisk 外挂程序 及 Asterisk 可加载模块 及 phpagi.conf 配置内容,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实现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/

 

这篇关于asterisk 外挂程序 及 Asterisk 可加载模块 及 phpagi.conf 配置内容的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/748835

相关文章

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Spring 基于XML配置 bean管理 Bean-IOC的方法

《Spring基于XML配置bean管理Bean-IOC的方法》:本文主要介绍Spring基于XML配置bean管理Bean-IOC的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录一. spring学习的核心内容二. 基于 XML 配置 bean1. 通过类型来获取 bean2. 通过

如何使用Nginx配置将80端口重定向到443端口

《如何使用Nginx配置将80端口重定向到443端口》这篇文章主要为大家详细介绍了如何将Nginx配置为将HTTP(80端口)请求重定向到HTTPS(443端口),文中的示例代码讲解详细,有需要的小伙... 目录1. 创建或编辑Nginx配置文件2. 配置HTTP重定向到HTTPS3. 配置HTTPS服务器

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

SpringBoot中配置Redis连接池的完整指南

《SpringBoot中配置Redis连接池的完整指南》这篇文章主要为大家详细介绍了SpringBoot中配置Redis连接池的完整指南,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以... 目录一、添加依赖二、配置 Redis 连接池三、测试 Redis 操作四、完整示例代码(一)pom.

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

如何在Mac上安装并配置JDK环境变量详细步骤

《如何在Mac上安装并配置JDK环境变量详细步骤》:本文主要介绍如何在Mac上安装并配置JDK环境变量详细步骤,包括下载JDK、安装JDK、配置环境变量、验证JDK配置以及可选地设置PowerSh... 目录步骤 1:下载JDK步骤 2:安装JDK步骤 3:配置环境变量1. 编辑~/.zshrc(对于zsh

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo