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

相关文章

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

hadoop开启回收站配置

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。 开启回收站功能参数说明 (1)默认值fs.trash.interval = 0,0表示禁用回收站;其他值表示设置文件的存活时间。 (2)默认值fs.trash.checkpoint.interval = 0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

wolfSSL参数设置或配置项解释

1. wolfCrypt Only 解释:wolfCrypt是一个开源的、轻量级的、可移植的加密库,支持多种加密算法和协议。选择“wolfCrypt Only”意味着系统或应用将仅使用wolfCrypt库进行加密操作,而不依赖其他加密库。 2. DTLS Support 解释:DTLS(Datagram Transport Layer Security)是一种基于UDP的安全协议,提供类似于

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。