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

相关文章

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

Springboot3+将ID转为JSON字符串的详细配置方案

《Springboot3+将ID转为JSON字符串的详细配置方案》:本文主要介绍纯后端实现Long/BigIntegerID转为JSON字符串的详细配置方案,s基于SpringBoot3+和Spr... 目录1. 添加依赖2. 全局 Jackson 配置3. 精准控制(可选)4. OpenAPI (Spri

maven私服配置全过程

《maven私服配置全过程》:本文主要介绍maven私服配置全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录使用Nexus作为 公司maven私服maven 私服setttings配置maven项目 pom配置测试效果总结使用Nexus作为 公司maven私

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos

python编写朋克风格的天气查询程序

《python编写朋克风格的天气查询程序》这篇文章主要为大家详细介绍了一个基于Python的桌面应用程序,使用了tkinter库来创建图形用户界面并通过requests库调用Open-MeteoAPI... 目录工具介绍工具使用说明python脚本内容如何运行脚本工具介绍这个天气查询工具是一个基于 Pyt

Ubuntu设置程序开机自启动的操作步骤

《Ubuntu设置程序开机自启动的操作步骤》在部署程序到边缘端时,我们总希望可以通电即启动我们写好的程序,本篇博客用以记录如何在ubuntu开机执行某条命令或者某个可执行程序,需要的朋友可以参考下... 目录1、概述2、图形界面设置3、设置为Systemd服务1、概述测试环境:Ubuntu22.04 带图

Nacos注册中心和配置中心的底层原理全面解读

《Nacos注册中心和配置中心的底层原理全面解读》:本文主要介绍Nacos注册中心和配置中心的底层原理的全面解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录临时实例和永久实例为什么 Nacos 要将服务实例分为临时实例和永久实例?1.x 版本和2.x版本的区别