⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chan_dahdi.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2006, Digium, Inc. * * Mark Spencer <markster@digium.com> * * 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. *//*! \file * * \brief DAHDI Pseudo TDM interface  * * \author Mark Spencer <markster@digium.com> *  * Connects to the DAHDI telephony library as well as  * libpri. Libpri is optional and needed only if you are * going to use ISDN connections. * * You need to install libraries before you attempt to compile * and install the DAHDI channel. * * \par See also * \arg \ref Config_dahdi * * \ingroup channel_drivers * * \todo Deprecate the "musiconhold" configuration option post 1.4 *//*** MODULEINFO	<depend>res_smdi</depend>	<depend>dahdi</depend>	<depend>tonezone</depend>	<depend>res_features</depend>	<use>pri</use> ***/#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 140115 $")#include <stdio.h>#include <string.h>#ifdef __NetBSD__#include <pthread.h>#include <signal.h>#else#include <sys/signal.h>#endif#include <errno.h>#include <stdlib.h>#if !defined(SOLARIS) && !defined(__FreeBSD__)#include <stdint.h>#endif#include <unistd.h>#include <sys/ioctl.h>#include <math.h>#include <ctype.h>#ifdef HAVE_PRI#include <libpri.h>#endif#include "asterisk/lock.h"#include "asterisk/channel.h"#include "asterisk/config.h"#include "asterisk/logger.h"#include "asterisk/module.h"#include "asterisk/pbx.h"#include "asterisk/options.h"#include "asterisk/file.h"#include "asterisk/ulaw.h"#include "asterisk/alaw.h"#include "asterisk/callerid.h"#include "asterisk/adsi.h"#include "asterisk/cli.h"#include "asterisk/cdr.h"#include "asterisk/features.h"#include "asterisk/musiconhold.h"#include "asterisk/say.h"#include "asterisk/tdd.h"#include "asterisk/app.h"#include "asterisk/dsp.h"#include "asterisk/astdb.h"#include "asterisk/manager.h"#include "asterisk/causes.h"#include "asterisk/term.h"#include "asterisk/utils.h"#include "asterisk/transcap.h"#include "asterisk/stringfields.h"#include "asterisk/abstract_jb.h"#include "asterisk/smdi.h"#include "asterisk/astobj.h"#define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */#include "asterisk/dahdi_compat.h"#include "asterisk/tonezone_compat.h"/*! Global jitterbuffer configuration - by default, jb is disabled */static struct ast_jb_conf default_jbconf ={	.flags = 0,	.max_size = -1,	.resync_threshold = -1,	.impl = ""};static struct ast_jb_conf global_jbconf;#ifndef DAHDI_TONEDETECT/* Work around older code with no tone detect */#define DAHDI_EVENT_DTMFDOWN 0#define DAHDI_EVENT_DTMFUP 0#endif/* define this to send PRI user-user information elements */#undef SUPPORT_USERUSER/*!  * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when * the user hangs up to reset the state machine so ring works properly. * This is used to be able to support kewlstart by putting the zhone in * groundstart mode since their forward disconnect supervision is entirely * broken even though their documentation says it isn't and their support * is entirely unwilling to provide any assistance with their channel banks * even though their web site says they support their products for life. *//* #define ZHONE_HACK *//*! \note * Define if you want to check the hook state for an FXO (FXS signalled) interface * before dialing on it.  Certain FXO interfaces always think they're out of * service with this method however. *//* #define DAHDI_CHECK_HOOKSTATE *//*! \brief Typically, how many rings before we should send Caller*ID */#define DEFAULT_CIDRINGS 1#define CHANNEL_PSEUDO -12#define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)/*! \brief Signaling types that need to use MF detection should be placed in this macro */#define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) static const char tdesc[] = "DAHDI Telephony Driver"#ifdef HAVE_PRI               " w/PRI"#endif;#define SIG_EM		DAHDI_SIG_EM#define SIG_EMWINK 	(0x0100000 | DAHDI_SIG_EM)#define SIG_FEATD	(0x0200000 | DAHDI_SIG_EM)#define	SIG_FEATDMF	(0x0400000 | DAHDI_SIG_EM)#define	SIG_FEATB	(0x0800000 | DAHDI_SIG_EM)#define	SIG_E911	(0x1000000 | DAHDI_SIG_EM)#define	SIG_FEATDMF_TA	(0x2000000 | DAHDI_SIG_EM)#define	SIG_FGC_CAMA	(0x4000000 | DAHDI_SIG_EM)#define	SIG_FGC_CAMAMF	(0x8000000 | DAHDI_SIG_EM)#define SIG_FXSLS	DAHDI_SIG_FXSLS#define SIG_FXSGS	DAHDI_SIG_FXSGS#define SIG_FXSKS	DAHDI_SIG_FXSKS#define SIG_FXOLS	DAHDI_SIG_FXOLS#define SIG_FXOGS	DAHDI_SIG_FXOGS#define SIG_FXOKS	DAHDI_SIG_FXOKS#define SIG_PRI		DAHDI_SIG_CLEAR#define	SIG_SF		DAHDI_SIG_SF#define SIG_SFWINK 	(0x0100000 | DAHDI_SIG_SF)#define SIG_SF_FEATD	(0x0200000 | DAHDI_SIG_SF)#define	SIG_SF_FEATDMF	(0x0400000 | DAHDI_SIG_SF)#define	SIG_SF_FEATB	(0x0800000 | DAHDI_SIG_SF)#define SIG_EM_E1	DAHDI_SIG_EM_E1#define SIG_GR303FXOKS	(0x0100000 | DAHDI_SIG_FXOKS)#define SIG_GR303FXSKS	(0x0100000 | DAHDI_SIG_FXSKS)#define NUM_SPANS 		32#define NUM_DCHANS		4	/*!< No more than 4 d-channels */#define MAX_CHANNELS	672		/*!< No more than a DS3 per trunk group */#define CHAN_PSEUDO	-2#define DCHAN_PROVISIONED (1 << 0)#define DCHAN_NOTINALARM  (1 << 1)#define DCHAN_UP          (1 << 2)#define DCHAN_AVAILABLE	(DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)static char defaultcic[64] = "";static char defaultozz[64] = "";static char progzone[10] = "";static int distinctiveringaftercid = 0;static int numbufs = 4;#ifdef HAVE_PRIstatic struct ast_channel inuse;#ifdef PRI_GETSET_TIMERSstatic int pritimers[PRI_MAX_TIMERS];#endifstatic int pridebugfd = -1;static char pridebugfilename[1024] = "";#endif/*! \brief Wait up to 16 seconds for first digit (FXO logic) */static int firstdigittimeout = 16000;/*! \brief How long to wait for following digits (FXO logic) */static int gendigittimeout = 8000;/*! \brief How long to wait for an extra digit, if there is an ambiguous match */static int matchdigittimeout = 3000;/*! \brief Protect the interface list (of dahdi_pvt's) */AST_MUTEX_DEFINE_STATIC(iflock);static int ifcount = 0;#ifdef HAVE_PRIAST_MUTEX_DEFINE_STATIC(pridebugfdlock);#endif/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not   when it's doing something critical. */AST_MUTEX_DEFINE_STATIC(monlock);/*! \brief This is the thread for the monitor which checks for input on the channels   which are not currently in use. */static pthread_t monitor_thread = AST_PTHREADT_NULL;static ast_cond_t ss_thread_complete;AST_MUTEX_DEFINE_STATIC(ss_thread_lock);AST_MUTEX_DEFINE_STATIC(restart_lock);static int ss_thread_count = 0;static int num_restart_pending = 0;static int restart_monitor(void);static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);static int dahdi_sendtext(struct ast_channel *c, const char *text);/*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */static inline int dahdi_get_event(int fd){	int j;	if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)		return -1;	return j;}/*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */static inline int dahdi_wait_event(int fd){	int i, j = 0;	i = DAHDI_IOMUX_SIGEVENT;	if (ioctl(fd, DAHDI_IOMUX, &i) == -1)		return -1;	if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)		return -1;	return j;}/*! Chunk size to read -- we use 20ms chunks to make things happy. */#define READ_SIZE 160#define MASK_AVAIL		(1 << 0)	/*!< Channel available for PRI use */#define MASK_INUSE		(1 << 1)	/*!< Channel currently in use */#define CALLWAITING_SILENT_SAMPLES	( (300 * 8) / READ_SIZE) /*!< 300 ms */#define CALLWAITING_REPEAT_SAMPLES	( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */#define CIDCW_EXPIRE_SAMPLES		( (500 * 8) / READ_SIZE) /*!< 500 ms */#define MIN_MS_SINCE_FLASH			( (2000) )	/*!< 2000 ms */#define DEFAULT_RINGT 				( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */struct dahdi_pvt;static int ringt_base = DEFAULT_RINGT;#ifdef HAVE_PRI#define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))#define PRI_CHANNEL(p) ((p) & 0xff)#define PRI_SPAN(p) (((p) >> 8) & 0xff)#define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)struct dahdi_pri {	pthread_t master;						/*!< Thread of master */	ast_mutex_t lock;						/*!< Mutex */	char idleext[AST_MAX_EXTENSION];				/*!< Where to idle extra calls */	char idlecontext[AST_MAX_CONTEXT];				/*!< What context to use for idle */	char idledial[AST_MAX_EXTENSION];				/*!< What to dial before dumping */	int minunused;							/*!< Min # of channels to keep empty */	int minidle;							/*!< Min # of "idling" calls to keep active */	int nodetype;							/*!< Node type */	int switchtype;							/*!< Type of switch to emulate */	int nsf;							/*!< Network-Specific Facilities */	int dialplan;							/*!< Dialing plan */	int localdialplan;						/*!< Local dialing plan */	char internationalprefix[10];					/*!< country access code ('00' for european dialplans) */	char nationalprefix[10];					/*!< area access code ('0' for european dialplans) */	char localprefix[20];						/*!< area access code + area code ('0'+area code for european dialplans) */	char privateprefix[20];						/*!< for private dialplans */	char unknownprefix[20];						/*!< for unknown dialplans */	int dchannels[NUM_DCHANS];					/*!< What channel are the dchannels on */	int trunkgroup;							/*!< What our trunkgroup is */	int mastertrunkgroup;						/*!< What trunk group is our master */	int prilogicalspan;						/*!< Logical span number within trunk group */	int numchans;							/*!< Num of channels we represent */	int overlapdial;						/*!< In overlap dialing mode */	int facilityenable;						/*!< Enable facility IEs */	struct pri *dchans[NUM_DCHANS];					/*!< Actual d-channels */	int dchanavail[NUM_DCHANS];					/*!< Whether each channel is available */	struct pri *pri;						/*!< Currently active D-channel */	int debug;	int fds[NUM_DCHANS];						/*!< FD's for d-channels */	int offset;	int span;	int resetting;	int resetpos;#ifdef HAVE_PRI_INBANDDISCONNECT	unsigned int inbanddisconnect:1;				/*!< Should we support inband audio after receiving DISCONNECT? */#endif	time_t lastreset;						/*!< time when unused channels were last reset */	long resetinterval;						/*!< Interval (in seconds) for resetting unused channels */	struct dahdi_pvt *pvts[MAX_CHANNELS];				/*!< Member channel pvt structs */	struct dahdi_pvt *crvs;						/*!< Member CRV structs */	struct dahdi_pvt *crvend;						/*!< Pointer to end of CRV structs */};static struct dahdi_pri pris[NUM_SPANS];#if 0#define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)#else#define DEFAULT_PRI_DEBUG 0#endifstatic inline void pri_rel(struct dahdi_pri *pri){	ast_mutex_unlock(&pri->lock);}#else/*! Shut up the compiler */struct dahdi_pri;#endif#define SUB_REAL	0			/*!< Active call */#define SUB_CALLWAIT	1			/*!< Call-Waiting call on hold */#define SUB_THREEWAY	2			/*!< Three-way call *//* Polarity states */#define POLARITY_IDLE   0#define POLARITY_REV    1static struct dahdi_distRings drings;struct distRingData {	int ring[3];};struct ringContextData {	char contextData[AST_MAX_CONTEXT];};struct dahdi_distRings {	struct distRingData ringnum[3];	struct ringContextData ringContext[3];};static char *subnames[] = {	"Real",	"Callwait",	"Threeway"};struct dahdi_subchannel {	int dfd;	struct ast_channel *owner;	int chan;	short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];	struct ast_frame f;		/*!< One frame for each channel.  How did this ever work before? */	unsigned int needringing:1;	unsigned int needbusy:1;	unsigned int needcongestion:1;	unsigned int needcallerid:1;	unsigned int needanswer:1;	unsigned int needflash:1;	unsigned int needhold:1;	unsigned int needunhold:1;	unsigned int linear:1;	unsigned int inthreeway:1;	struct dahdi_confinfo curconf;};#define CONF_USER_REAL		(1 << 0)#define CONF_USER_THIRDCALL	(1 << 1)#define MAX_SLAVES	4static struct dahdi_pvt {	ast_mutex_t lock;	struct ast_channel *owner;			/*!< Our current active owner (if applicable) */							/*!< Up to three channels can be associated with this call */			struct dahdi_subchannel sub_unused;		/*!< Just a safety precaution */	struct dahdi_subchannel subs[3];			/*!< Sub-channels */	struct dahdi_confinfo saveconf;			/*!< Saved conference info */	struct dahdi_pvt *slaves[MAX_SLAVES];		/*!< Slave to us (follows our conferencing) */	struct dahdi_pvt *master;				/*!< Master to us (we follow their conferencing) */	int inconference;				/*!< If our real should be in the conference */		int buf_no;					/*!< Number of buffers */	int buf_policy;				/*!< Buffer policy */	int sig;					/*!< Signalling style */	int radio;					/*!< radio type */	int outsigmod;					/*!< Outbound Signalling style (modifier) */	int oprmode;					/*!< "Operator Services" mode */	struct dahdi_pvt *oprpeer;				/*!< "Operator Services" peer tech_pvt ptr */	float rxgain;	float txgain;	int tonezone;					/*!< tone zone for this chan, or -1 for default */	struct dahdi_pvt *next;				/*!< Next channel in list */	struct dahdi_pvt *prev;				/*!< Prev channel in list */	/* flags */	unsigned int adsi:1;	unsigned int answeronpolarityswitch:1;	unsigned int busydetect:1;	unsigned int callreturn:1;	unsigned int callwaiting:1;	unsigned int callwaitingcallerid:1;	unsigned int cancallforward:1;	unsigned int canpark:1;	unsigned int confirmanswer:1;			/*!< Wait for '#' to confirm answer */	unsigned int destroy:1;	unsigned int didtdd:1;				/*!< flag to say its done it once */	unsigned int dialednone:1;	unsigned int dialing:1;	unsigned int digital:1;	unsigned int dnd:1;	unsigned int echobreak:1;	unsigned int echocanbridged:1;	unsigned int echocanon:1;	unsigned int faxhandled:1;			/*!< Has a fax tone already been handled? */	unsigned int firstradio:1;	unsigned int hanguponpolarityswitch:1;	unsigned int hardwaredtmf:1;	unsigned int hidecallerid:1;	unsigned int hidecalleridname:1;      /*!< Hide just the name not the number for legacy PBX use */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -