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

相关文章

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

Debian系和Redhat系防火墙配置方式

《Debian系和Redhat系防火墙配置方式》文章对比了Debian系UFW和Redhat系Firewalld防火墙的安装、启用禁用、端口管理、规则查看及注意事项,强调SSH端口需开放、规则持久化,... 目录Debian系UFW防火墙1. 安装2. 启用与禁用3. 基本命令4. 注意事项5. 示例配置R

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q

Redis MCP 安装与配置指南

《RedisMCP安装与配置指南》本文将详细介绍如何安装和配置RedisMCP,包括快速启动、源码安装、Docker安装、以及相关的配置参数和环境变量设置,感兴趣的朋友一起看看吧... 目录一、Redis MCP 简介二、安www.chinasem.cn装 Redis MCP 服务2.1 快速启动(推荐)2.

Spring Boot配置和使用两个数据源的实现步骤

《SpringBoot配置和使用两个数据源的实现步骤》本文详解SpringBoot配置双数据源方法,包含配置文件设置、Bean创建、事务管理器配置及@Qualifier注解使用,强调主数据源标记、代... 目录Spring Boot配置和使用两个数据源技术背景实现步骤1. 配置数据源信息2. 创建数据源Be

linux批量替换文件内容的实现方式

《linux批量替换文件内容的实现方式》本文总结了Linux中批量替换文件内容的几种方法,包括使用sed替换文件夹内所有文件、单个文件内容及逐行字符串,强调使用反引号和绝对路径,并分享个人经验供参考... 目录一、linux批量替换文件内容 二、替换文件内所有匹配的字符串 三、替换每一行中全部str1为st

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

Spring Boot Maven 插件如何构建可执行 JAR 的核心配置

《SpringBootMaven插件如何构建可执行JAR的核心配置》SpringBoot核心Maven插件,用于生成可执行JAR/WAR,内置服务器简化部署,支持热部署、多环境配置及依赖管理... 目录前言一、插件的核心功能与目标1.1 插件的定位1.2 插件的 Goals(目标)1.3 插件定位1.4 核

RabbitMQ消息总线方式刷新配置服务全过程

《RabbitMQ消息总线方式刷新配置服务全过程》SpringCloudBus通过消息总线与MQ实现微服务配置统一刷新,结合GitWebhooks自动触发更新,避免手动重启,提升效率与可靠性,适用于配... 目录前言介绍环境准备代码示例测试验证总结前言介绍在微服务架构中,为了更方便的向微服务实例广播消息,