isdn_lib.c

来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· C语言 代码 · 共 2,927 行 · 第 1/5 页

C
2,927
字号
/* * Chan_Misdn -- Channel Driver for Asterisk * * Interface to mISDN * * Copyright (C) 2004, Christian Richter * * Christian Richter <crich@beronet.com> * * This program is free software, distributed under the terms of * the GNU General Public License */#include "isdn_lib_intern.h"int misdn_ibuf_freecount(void *buf){	return ibuf_freecount( (ibuffer_t*)buf);}int misdn_ibuf_usedcount(void *buf){	return ibuf_usedcount( (ibuffer_t*)buf);}void misdn_ibuf_memcpy_r(char *to, void *buf, int len){	ibuf_memcpy_r( to, (ibuffer_t*)buf, len);}void misdn_ibuf_memcpy_w(void *buf, char *from,  int len){	ibuf_memcpy_w((ibuffer_t*)buf, from, len);}struct misdn_stack* get_misdn_stack( void );int misdn_lib_is_ptp(int port){	struct misdn_stack *stack=get_misdn_stack();	for ( ; stack; stack=stack->next) {		if (stack->port == port) return stack->ptp;	}	return -1;}struct misdn_stack* get_stack_by_bc(struct misdn_bchannel *bc){	struct misdn_stack *stack=get_misdn_stack();	if (!bc) return NULL;		for ( ; stack; stack=stack->next) {		int i;		for (i=0; i <stack->b_num; i++) {			if ( bc->port == stack->port) return stack;		}	}	return NULL;}void get_show_stack_details(int port, char *buf){	struct misdn_stack *stack=get_misdn_stack();		for ( ; stack; stack=stack->next) {		if (stack->port == port) break;	}		if (stack) {		sprintf(buf, "* Stack Addr: Port %d Type %s Prot. %s L2Link %s L1Link:%s", stack->upper_id & IF_CONTRMASK, stack->mode==NT_MODE?"NT":"TE", stack->ptp?"PTP":"PMP", stack->l2link?"UP":"DOWN", stack->l1link?"UP":"DOWN");	} else {		buf[0]=0;	}	}static int nt_err_cnt =0 ;enum global_states {	MISDN_INITIALIZING,	MISDN_INITIALIZED} ;static enum global_states  global_state=MISDN_INITIALIZING;#include <mISDNuser/net_l2.h>#include <mISDNuser/tone.h>#include <unistd.h>#include <semaphore.h>#include <pthread.h>#include <signal.h>#include "isdn_lib.h"struct misdn_lib {	int midev;	int midev_nt;	pthread_t event_thread;	pthread_t event_handler_thread;  	void *user_data;	msg_queue_t upqueue;	msg_queue_t activatequeue;   	sem_t new_msg;  	struct misdn_stack *stack_list;} ;#ifndef ECHOCAN_ON#define ECHOCAN_ON 123#define ECHOCAN_OFF 124#endif#define MISDN_DEBUG 0struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id);int setup_bc(struct misdn_bchannel *bc);int manager_isdn_handler(iframe_t *frm ,msg_t *msg);int misdn_lib_port_restart(int port);extern struct isdn_msg msgs_g[]; #define ISDN_PID_L3_B_USER 0x430000ff#define ISDN_PID_L4_B_USER 0x440000ff/* #define MISDN_IBUF_SIZE 1024 */#define MISDN_IBUF_SIZE 512/*  Fine Tuning of Inband  Signalling time */#define TONE_ALERT_CNT 41 /*  1 Sec  */#define TONE_ALERT_SILENCE_CNT 200 /*  4 Sec */#define TONE_BUSY_CNT 20 /*  ? */#define TONE_BUSY_SILENCE_CNT 48 /*  ? */static int  entity;static struct misdn_lib *glob_mgr;unsigned char tone_425_flip[TONE_425_SIZE];unsigned char tone_silence_flip[TONE_SILENCE_SIZE];static void misdn_lib_isdn_event_catcher(void *arg);static int handle_event_nt(void *dat, void *arg);void stack_holder_add(struct misdn_stack *stack, struct misdn_bchannel *holder);void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holder);struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned long l3id);/* from isdn_lib.h */int init_bc(struct misdn_stack * stack,  struct misdn_bchannel *bc, int midev, int port, int bidx, char *msn, int firsttime);struct misdn_stack* stack_te_init(int midev,  int port, int ptp);void stack_te_destroy(struct misdn_stack* stack);	/* user iface */int te_lib_init( void ) ; /* returns midev */void te_lib_destroy(int midev) ;struct misdn_bchannel *manager_find_bc_by_pid(int pid);struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc);unsigned char * manager_flip_buf_bits ( unsigned char * buf , int len);void manager_ph_control_block(struct misdn_bchannel *bc, int c1, void *c2, int c2_len);void manager_clean_bc(struct misdn_bchannel *bc );void manager_bchannel_setup (struct misdn_bchannel *bc);void manager_bchannel_cleanup (struct misdn_bchannel *bc);int isdn_msg_get_index(struct isdn_msg msgs[], msg_t *frm, int nt);enum event_e isdn_msg_get_event(struct isdn_msg msgs[], msg_t *frm, int nt);int isdn_msg_parse_event(struct isdn_msg msgs[], msg_t *frm, struct misdn_bchannel *bc, int nt);char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt);msg_t * isdn_msg_build_event(struct isdn_msg msgs[], struct misdn_bchannel *bc, enum event_e event, int nt);void ec_chunk( struct misdn_bchannel *bc, unsigned char *rxchunk, unsigned char *txchunk, int chunk_size);	/* end */int bchdev_echocancel_activate(struct misdn_bchannel* dev);void bchdev_echocancel_deactivate(struct misdn_bchannel* dev);/* end */static char *bearer2str(int cap) {	static char *bearers[]={		"Speech",		"Audio 3.1k",		"Unres Digital",		"Res Digital",		"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;	default:		return bearers[4];		break;	}}static char flip_table[256];void init_flip_bits(void){	int i,k;		for (i = 0 ; i < 256 ; i++) {		unsigned char sample = 0 ;		for (k = 0; k<8; k++) {			if ( i & 1 << k ) sample |= 0x80 >>  k;		}		flip_table[i] = sample;	}}static unsigned char * flip_buf_bits ( unsigned char * buf , int len){	int i;	char * start = buf;		for (i = 0 ; i < len; i++) {		buf[i] = flip_table[buf[i]];	}		return start;}msg_t *create_l2msg(int prim, int dinfo, int size) /* NT only */{	int i = 0;	msg_t *dmsg;  	while(i < 10)	{		dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);		if (dmsg)			return(dmsg);      		if (!i)			printf("cannot allocate memory, trying again...\n");		i++;		usleep(300000);	}	printf("cannot allocate memory, system overloaded.\n");	exit(-1);}msg_t *create_l3msg(int prim, int mt, int dinfo, int size, int ntmode){	int i = 0;	msg_t *dmsg;	Q931_info_t *qi;	iframe_t *frm;  	if (!ntmode)		size = sizeof(Q931_info_t)+2;  	while(i < 10) {		if (ntmode) {			dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);			if (dmsg) {				return(dmsg);			}		} else {			dmsg = alloc_msg(size+256+mISDN_HEADER_LEN+DEFAULT_HEADROOM);			if (dmsg)			{				memset(msg_put(dmsg,size+mISDN_HEADER_LEN), 0, size+mISDN_HEADER_LEN);				frm = (iframe_t *)dmsg->data;				frm->prim = prim;				frm->dinfo = dinfo;				qi = (Q931_info_t *)(dmsg->data + mISDN_HEADER_LEN);				qi->type = mt;				return(dmsg);			}		}    		if (!i) printf("cannot allocate memory, trying again...\n");		i++;		usleep(300000);	}	printf("cannot allocate memory, system overloaded.\n");	exit(-1);}int send_msg (int midev, struct misdn_bchannel *bc, msg_t *dmsg){	iframe_t *frm;	frm = (iframe_t *)dmsg->data;	struct misdn_stack *stack=get_stack_by_bc(bc);		frm->addr = (stack->upper_id &  IF_ADDRMASK) | IF_DOWN ;	frm->dinfo = bc->l3_id;  	frm->len = (dmsg->len) - mISDN_HEADER_LEN;  	mISDN_write(midev, dmsg->data, dmsg->len, TIMEOUT_1SEC);  	free_msg(dmsg);	return 0;}static int mypid=0;int misdn_cap_is_speech(int cap)/** Poor mans version **/{	if ( (cap != INFO_CAPABILITY_DIGITAL_UNRESTRICTED) &&	     (cap != INFO_CAPABILITY_DIGITAL_RESTRICTED) ) return 1;	return 0;}int misdn_inband_avail(struct misdn_bchannel *bc){	/*if ! early_bconnect we have never inband available*/	if ( ! bc->early_bconnect ) return 0;		switch (bc->progress_indicator) {	case INFO_PI_INBAND_AVAILABLE:	case INFO_PI_CALL_NOT_E2E_ISDN:	case INFO_PI_CALLED_NOT_ISDN:		return 1;	default:		return 0;	}	return 0;}void dump_chan_list(struct misdn_stack *stack){	int i;	for (i=0; i <stack->b_num; i++) {		cb_log(3, stack->port, "Idx:%d stack->cchan:%d Chan:%d\n",i,stack->channels[i], i+1);	}}static int find_free_chan_in_stack(struct misdn_stack *stack, int channel){	int i;	if (channel < 0 || channel > MAX_BCHANS) {		cb_log(4, stack->port, " !! out of bound call to find_free_chan_in_stack! (port:%d ch:%d)\n", stack->port, channel);		return 0;	}		channel--;  	for (i = 0; i < stack->b_num; i++) {		if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 Dchannel ;) and work with chan preselection */			if (!stack->channels[i]) {				cb_log (4, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);				stack->channels[i] = 1;				return i+1;			}		}	}	cb_log (4, stack->port, " !! NO FREE CHAN IN STACK\n");	dump_chan_list(stack);  	return 0;}int empty_chan_in_stack(struct misdn_stack *stack, int channel){	cb_log (4, stack?stack->port:0, " --> empty chan %d\n",channel); 	stack->channels[channel-1] = 0;	dump_chan_list(stack);	return 0;}void empty_bc(struct misdn_bchannel *bc){	bc->state=STATE_NOTHING;		bc->channel = 0;	bc->in_use = 0;	bc->send_dtmf=0;	bc->nodsp=0;	bc->nojitter=0;		bc->time_usec=0;		bc->rxgain=0;	bc->txgain=0;	bc->crypt=0;	bc->curptx=0; bc->curprx=0;		bc->crypt_key[0] = 0;		bc->tone=TONE_NONE;	bc->tone_cnt2 = bc->tone_cnt=0;  	bc->dnumplan=NUMPLAN_UNKNOWN;	bc->onumplan=NUMPLAN_UNKNOWN;	bc->rnumplan=NUMPLAN_UNKNOWN;		bc->active = 0;	bc->early_bconnect = 1;		bc->ec_enable = 0;	bc->ec_deftaps = 128;	bc->ec_whenbridged = 0;	bc->ec_training = 1;			bc->orig=0;  	bc->cause=16;	bc->out_cause=16;	bc->pres=0 ; /* screened */		bc->evq=EVENT_NOTHING;	bc->progress_coding=0;	bc->progress_location=0;	bc->progress_indicator=0;	/** Set Default Bearer Caps **/	bc->capability=INFO_CAPABILITY_SPEECH;	bc->law=INFO_CODEC_ALAW;	bc->mode=0;	bc->rate=0;	bc->user1=0;	bc->async=0;	bc->urate=0;				bc->info_dad[0] = 0;	bc->display[0] = 0;	bc->infos_pending[0] = 0;	bc->oad[0] = 0;	bc->dad[0] = 0;	bc->orig_dad[0] = 0;		bc->facility=FACILITY_NONE;	bc->facility_calldeflect_nr[0]=0;	bc->te_choose_channel = 0;}int clean_up_bc(struct misdn_bchannel *bc){	int ret=0;	unsigned char buff[32];	struct misdn_stack * stack;		if (!bc  ) return -1;	stack=get_stack_by_bc(bc);	if (!stack) return -1;		if (!bc->upset) {		cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid);		return -1;	}  	cb_log(5, stack->port, "$$$ Cleaning up bc with stid :%x\n", bc->b_stid);			if ( misdn_cap_is_speech(bc->capability) && bc->ec_enable) {		manager_ec_disable(bc);	}		mISDN_write_frame(stack->midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);			bc->b_stid = 0;		bc->upset=0;		return ret;}void clear_l3(struct misdn_stack *stack){	int i;	for (i=0; i<stack->b_num; i++) {		if (global_state == MISDN_INITIALIZED)  {			cb_event(EVENT_CLEANUP, &stack->bc[i], glob_mgr->user_data);			empty_chan_in_stack(stack,i+1);			empty_bc(&stack->bc[i]);			clean_up_bc(&stack->bc[i]);					}			} }int set_chan_in_stack(struct misdn_stack *stack, int channel){	stack->channels[channel-1] = 1;  	return 0;}int chan_in_stack_free(struct misdn_stack *stack, int channel){	if (stack->channels[channel-1])		return 0;  	return 1;}static int newteid=0;#ifdef MISDNUSER_JOLLY#define MAXPROCS 0x100#else#define MAXPROCS 0x10#endifint misdn_lib_get_l1_up(struct misdn_stack *stack){	/* Pull Up L1 if we have JOLLY */ 	iframe_t act;	act.prim = PH_ACTIVATE | REQUEST; 	act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ;	act.dinfo = 0;	act.len = 0;	return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);}int misdn_lib_get_l2_up(struct misdn_stack *stack){		if (stack->ptp && (stack->mode == NT_MODE) ) {		msg_t *dmsg;		/* L2 */		dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);				if (stack->nst.manager_l3(&stack->nst, dmsg))			free_msg(dmsg);			} else {		iframe_t act;				act.prim = DL_ESTABLISH | REQUEST;

⌨️ 快捷键说明

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