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 + -
显示快捷键?