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

📄 chan_misdn.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Asterisk -- An open source telephony toolkit. *  * Copyright (C) 2004 - 2006, Christian Richter * * Christian Richter <crich@beronet.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 the chan_misdn channel driver for Asterisk * \author Christian Richter <crich@beronet.com> * * \ingroup channel_drivers *//*** MODULEINFO	<depend>isdnnet</depend>	<depend>misdn</depend>	<depend>suppserv</depend> ***/#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 136241 $")#include <stdio.h>#include <pthread.h>#include <string.h>#include <sys/socket.h>#include <sys/time.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <arpa/inet.h>#include <fcntl.h>#include <sys/ioctl.h>#include <signal.h>#include <sys/file.h>#include <semaphore.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/io.h"#include "asterisk/frame.h"#include "asterisk/translate.h"#include "asterisk/cli.h"#include "asterisk/musiconhold.h"#include "asterisk/dsp.h"#include "asterisk/translate.h"#include "asterisk/config.h"#include "asterisk/file.h"#include "asterisk/callerid.h"#include "asterisk/indications.h"#include "asterisk/app.h"#include "asterisk/features.h"#include "asterisk/term.h"#include "asterisk/sched.h"#include "asterisk/stringfields.h"#include "chan_misdn_config.h"#include "isdn_lib.h"char global_tracefile[BUFFERSIZE+1];static int g_config_initialized=0;struct misdn_jb{	int size;	int upper_threshold;	char *samples, *ok;	int wp,rp;	int state_empty;	int state_full;	int state_buffer;	int bytes_wrote;	ast_mutex_t mutexjb;};/* allocates the jb-structure and initialize the elements*/struct misdn_jb *misdn_jb_init(int size, int upper_threshold);/* frees the data and destroys the given jitterbuffer struct */void misdn_jb_destroy(struct misdn_jb *jb);/* fills the jitterbuffer with len data returns < 0 if there was anerror (buffer overrun). */int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);/* gets len bytes out of the jitterbuffer if available, else only theavailable data is returned and the return value indicates the numberof data. */int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);/* BEGIN: chan_misdn.h */ast_mutex_t release_lock;enum misdn_chan_state {	MISDN_NOTHING=0,	/*!< at beginning */	MISDN_WAITING4DIGS, /*!<  when waiting for infos */	MISDN_EXTCANTMATCH, /*!<  when asterisk couldn't match our ext */	MISDN_INCOMING_SETUP, /*!<  for incoming setups*/	MISDN_DIALING, /*!<  when pbx_start */	MISDN_PROGRESS, /*!<  we got a progress */	MISDN_PROCEEDING, /*!<  we got a progress */	MISDN_CALLING, /*!<  when misdn_call is called */	MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */	MISDN_ALERTING, /*!<  when Alerting */	MISDN_BUSY, /*!<  when BUSY */	MISDN_CONNECTED, /*!<  when connected */	MISDN_PRECONNECTED, /*!<  when connected */	MISDN_DISCONNECTED, /*!<  when connected */	MISDN_RELEASED, /*!<  when connected */	MISDN_BRIDGED, /*!<  when bridged */	MISDN_CLEANING, /*!< when hangup from * but we were connected before */	MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */	MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */	/* misdn_hangup */	MISDN_HOLDED, /*!< if this chan is holded */	MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */  };#define ORG_AST 1#define ORG_MISDN 2struct hold_info {	int port;	int channel;};struct chan_list {  	char allowed_bearers[BUFFERSIZE+1];		enum misdn_chan_state state;	int need_queue_hangup;	int need_hangup;	int need_busy;		int noautorespond_on_setup;		int originator;	int norxtone;	int notxtone; 	int toggle_ec;		int incoming_early_audio;	int ignore_dtmf;	int pipe[2];	char ast_rd_buf[4096];	struct ast_frame frame;	int faxdetect; /* 0:no 1:yes 2:yes+nojump */	int faxdetect_timeout;	struct timeval faxdetect_tv;	int faxhandled;	int ast_dsp;	int jb_len;	int jb_upper_threshold;	struct misdn_jb *jb;		struct ast_dsp *dsp;	struct ast_trans_pvt *trans;  	struct ast_channel * ast;	int dummy;  	struct misdn_bchannel *bc;	struct hold_info hold_info;	unsigned int l3id;	int addr;	char context[BUFFERSIZE];	int zero_read_cnt;	int dropped_frame_cnt;	int far_alerting;	int nttimeout;	int other_pid;	struct chan_list *other_ch;	const struct ind_tone_zone_sound *ts;		int overlap_dial;	int overlap_dial_task;	ast_mutex_t overlap_tv_lock;	struct timeval overlap_tv;  	struct chan_list *peer;	struct chan_list *next;	struct chan_list *prev;	struct chan_list *first;};void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);struct robin_list {	char *group;	int port;	int channel;	struct robin_list *next;	struct robin_list *prev;};static struct robin_list *robin = NULL;static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);static inline void free_robin_list_r (struct robin_list *r){        if (r) {                if (r->next) free_robin_list_r(r->next);                if (r->group) free(r->group);                free(r);        }}static void free_robin_list ( void ){	free_robin_list_r(robin);	robin = NULL;}static struct robin_list* get_robin_position (char *group) {	struct robin_list *new;	struct robin_list *iter = robin;	for (; iter; iter = iter->next) {		if (!strcasecmp(iter->group, group))			return iter;	}	new = (struct robin_list *)calloc(1, sizeof(struct robin_list));	new->group = strndup(group, strlen(group));	new->port = 0;	new->channel = 0;	if (robin) {		new->next = robin;		robin->prev = new;	}	robin = new;	return robin;}/* the main schedule context for stuff like l1 watcher, overlap dial, ... */static struct sched_context *misdn_tasks = NULL;static pthread_t misdn_tasks_thread;static int *misdn_ports;static void chan_misdn_log(int level, int port, char *tmpl, ...);static struct ast_channel *misdn_new(struct chan_list *cl, int state,  char *exten, char *callerid, int format, int port, int c);static void send_digit_to_chan(struct chan_list *cl, char digit );static void hangup_chan(struct chan_list *ch);static int pbx_start_chan(struct chan_list *ch);#define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt#define MISDN_ASTERISK_PVT(ast) 1#include <asterisk/strings.h>/* #define MISDN_DEBUG 1 */static const char misdn_type[] = "mISDN";static int tracing = 0 ;/* Only alaw and mulaw is allowed for now */static int prefformat =  AST_FORMAT_ALAW ; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */static int *misdn_debug;static int *misdn_debug_only;static int max_ports;static int *misdn_in_calls;static int *misdn_out_calls;struct chan_list dummy_cl;struct chan_list *cl_te=NULL;ast_mutex_t cl_te_lock;static enum event_response_ecb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);static int dialtone_indicate(struct chan_list *cl);static int hanguptone_indicate(struct chan_list *cl);static int stop_indicate(struct chan_list *cl);static int start_bc_tones(struct chan_list *cl);static int stop_bc_tones(struct chan_list *cl);static void release_chan(struct misdn_bchannel *bc);static int misdn_check_l2l1(struct ast_channel *chan, void *data);static int misdn_set_opt_exec(struct ast_channel *chan, void *data);static int misdn_facility_exec(struct ast_channel *chan, void *data);int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);void debug_numplan(int port, int numplan, char *type);int add_out_calls(int port);int add_in_calls(int port);#ifdef MISDN_1_2static int update_pipeline_config(struct misdn_bchannel *bc);#elsestatic int update_ec_config(struct misdn_bchannel *bc);#endif/*************** Helpers *****************/static struct chan_list * get_chan_by_ast(struct ast_channel *ast){	struct chan_list *tmp;  	for (tmp=cl_te; tmp; tmp = tmp->next) {		if ( tmp->ast == ast ) return tmp;	}  	return NULL;}static struct chan_list * get_chan_by_ast_name(char *name){	struct chan_list *tmp;  	for (tmp=cl_te; tmp; tmp = tmp->next) {		if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;	}  	return NULL;}struct allowed_bearers {	int cap;	int val;	char *name;	int deprecated;};static struct allowed_bearers allowed_bearers_array[]= {	{INFO_CAPABILITY_SPEECH,1,"speech"},	{INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},	{INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},	{INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restricted"},	{INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced", 1}, /* Allow misspelling for backwards compatibility */	{INFO_CAPABILITY_VIDEO,16,"video"}};static char *bearer2str(int cap) {	static char *bearers[]={		"Speech",		"Audio 3.1k",		"Unres Digital",		"Res Digital",		"Video",		"Unknown Bearer"	};		switch (cap) {	case INFO_CAPABILITY_SPEECH:		return bearers[0];		break;	case INFO_CAPABILITY_AUDIO_3_1K:		return bearers[1];		break;	case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:		return bearers[2];		break;	case INFO_CAPABILITY_DIGITAL_RESTRICTED:		return bearers[3];		break;	case INFO_CAPABILITY_VIDEO:		return bearers[4];		break;	default:		return bearers[5];		break;	}}static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc){	switch (fac->Function) {	case Fac_CD:		chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,					   fac->u.CDeflection.PresentationAllowed ? "yes" : "no");		break;	case Fac_AOCDCurrency:		if (fac->u.AOCDcur.chargeNotAvailable)			chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");		else if (fac->u.AOCDcur.freeOfCharge)			chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");		else if (fac->u.AOCDchu.billingId >= 0)			chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",						   fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,						   (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);		else			chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",						   fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,						   (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");		break;	case Fac_AOCDChargingUnit:		if (fac->u.AOCDchu.chargeNotAvailable)			chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");		else if (fac->u.AOCDchu.freeOfCharge)			chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");		else if (fac->u.AOCDchu.billingId >= 0)			chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",						   fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);		else			chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",						   fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");		break;	default:		chan_misdn_log(1,bc->port," --> unknown\n");	}}static void print_bearer(struct misdn_bchannel *bc) {		chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));		switch(bc->law) {	case INFO_CODEC_ALAW:		chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");		break;	case INFO_CODEC_ULAW:		chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");		break;	}}static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc){	char buf[128];	if (!ast)		return;	if (originator == ORG_AST) {		ast = ast_bridged_channel(ast);		if (!ast)			return;	}

⌨️ 快捷键说明

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