isdn_lib.c

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

C
2,927
字号
	if (ret < mISDN_HEADER_LEN) {	noentity:		fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n",strerror(errno));		exit(-1);	}  	entity = frm->dinfo & 0xffff ;  	if (!entity)		goto noentity;	return midev;  }void te_lib_destroy(int midev){	char buf[1024];	mISDN_write_frame(midev, buf, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);	cb_log(4, 0, "Entetity deleted\n");	mISDN_close(midev);	cb_log(4, 0, "midev closed\n");}void misdn_lib_transfer(struct misdn_bchannel* holded_bc){	holded_bc->holded=0;}struct misdn_bchannel *manager_find_bc_by_pid(int pid){	struct misdn_stack *stack;	int i;  	for (stack=glob_mgr->stack_list;	     stack;	     stack=stack->next) {		for (i=0; i<stack->b_num; i++)			if (stack->bc[i].pid == pid) return &stack->bc[i];	}  	return NULL;}struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc){	struct misdn_stack *stack=get_stack_by_bc(bc);	return find_bc_holded(stack);}struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel){	struct misdn_stack *stack;	int i;		if (channel < 0 || channel > MAX_BCHANS)		return NULL;	for (stack=glob_mgr->stack_list; stack; stack=stack->next) {    		if (stack->port == port) {			if (channel > 0) {				if (channel <= stack->b_num) {					for (i = 0; i < stack->b_num; i++) {						if (stack->bc[i].in_use && stack->bc[i].channel == channel) {							return NULL;						}					}				} else					return NULL;			}			for (i = 0; i < stack->b_num; i++) {				if (!stack->bc[i].in_use) {					stack->bc[i].channel = channel;					stack->bc[i].channel_preselected = channel?1:0;					stack->bc[i].in_use = 1;					return &stack->bc[i];				}			}			return NULL;		}	}	return NULL;}void misdn_lib_log_ies(struct misdn_bchannel *bc){	if (!bc) return;	struct misdn_stack *stack=get_stack_by_bc(bc);	if (!stack) return;		cb_log(2, stack->port, " --> mode:%s cause:%d ocause:%d rad:%s\n", stack->mode==NT_MODE?"NT":"TE", bc->cause, bc->out_cause, bc->rad);		cb_log(2, stack->port,	       " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c\n",	       bc->info_dad,	       bc->onumplan>=0?'0'+bc->onumplan:' ',	       bc->dnumplan>=0?'0'+bc->dnumplan:' ',	       bc->rnumplan>=0?'0'+bc->rnumplan:' '		);		cb_log(2, stack->port, " --> channel:%d caps:%s pi:%x keypad:%s\n", bc->channel, bearer2str(bc->capability),bc->progress_indicator, bc->keypad);	cb_log(3, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1);		cb_log(3, stack->port, " --> pid:%d addr:%x l3id:%x\n", bc->pid, bc->addr, bc->l3_id);	cb_log(4, stack->port, " --> bc:%x h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);}int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ){	msg_t *msg; 	int err = -1 ;  	if (!bc) goto ERR; 		struct misdn_stack *stack=get_stack_by_bc(bc);		if ( stack->mode == NT_MODE && !stack->l1link) {		/** Queue Event **/		bc->evq=event;		cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0));		{ /* Pull Up L1 */ 			iframe_t act;			act.prim = PH_ACTIVATE | REQUEST; 			act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ;			act.dinfo = 0;			act.len = 0;			mISDN_write(glob_mgr->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);		}				return 0;	}		cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s port:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, stack->port);	misdn_lib_log_ies(bc);		switch (event) {	case EVENT_SETUP:		if (create_process(glob_mgr->midev, bc)<0) {			cb_log(0,  stack->port, " No free channel at the moment @ send_event\n");			err=-ENOCHAN;			goto ERR;		}		break;	case EVENT_CONNECT:	case EVENT_PROGRESS:	case EVENT_ALERTING:	case EVENT_PROCEEDING:	case EVENT_SETUP_ACKNOWLEDGE:	case EVENT_RETRIEVE_ACKNOWLEDGE:				if (stack->mode == NT_MODE) {			if (bc->channel <=0 ) { /*  else we have the channel already */				bc->channel = find_free_chan_in_stack(stack, 0);				if (!bc->channel) {					cb_log(0, stack->port, " No free channel at the moment\n");					err=-ENOCHAN;					goto ERR;				}			}			/* Its that i generate channels */		}				setup_bc(bc);						if ( event == EVENT_CONNECT ) {			if ( *bc->crypt_key ) {				cb_log(4, stack->port,  " --> ENABLING BLOWFISH port:%d channel:%d oad%d:%s dad%d:%s \n", stack->port, bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);								manager_ph_control_block(bc,  BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );			}						if ( misdn_cap_is_speech(bc->capability)) {				if (!bc->nodsp) manager_ph_control(bc,  DTMF_TONE_START, 0);								if (bc->ec_enable) manager_ec_enable(bc);								if (bc->txgain != 0) {					cb_log(4, stack->port,  "--> Changing txgain to %d\n", bc->txgain);					manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);				}								if ( bc->rxgain != 0 ) {					cb_log(4, stack->port,  "--> Changing rxgain to %d\n", bc->rxgain);					manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);				}			}		}				if (event == EVENT_RETRIEVE_ACKNOWLEDGE) {			manager_bchannel_activate(bc);		}				break;    	case EVENT_HOLD_ACKNOWLEDGE:	{		struct misdn_bchannel *holded_bc=malloc(sizeof(struct misdn_bchannel));				memcpy(holded_bc,bc,sizeof(struct misdn_bchannel));				holded_bc->holded=1;		stack_holder_add(stack,holded_bc);				if (stack->mode == NT_MODE) {			empty_chan_in_stack(stack,bc->channel);			empty_bc(bc);			clean_up_bc(bc);		}				/** we set it up later at RETRIEVE_ACK again.**/		holded_bc->upset=0;		holded_bc->active=0;				cb_event( EVENT_NEW_BC, holded_bc, glob_mgr->user_data);	}	break;		case EVENT_RELEASE:		break;			case EVENT_RELEASE_COMPLETE:		empty_chan_in_stack(stack,bc->channel);		empty_bc(bc);		clean_up_bc(bc);		break;    	case EVENT_CONNECT_ACKNOWLEDGE:				if (misdn_cap_is_speech(bc->capability)) {			if (  !bc->nodsp) manager_ph_control(bc,  DTMF_TONE_START, 0);			if (bc->ec_enable) manager_ec_enable(bc);			if ( bc->txgain != 0 ) {				cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);				manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);			}			if ( bc->rxgain != 0 ) {				cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain);				manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);			}		}		break;    	default:		break;	}  	/* Later we should think about sending bchannel data directly to misdn. */	msg = isdn_msg_build_event(msgs_g, bc, event, stack->mode==NT_MODE?1:0);	msg_queue_tail(&stack->downqueue, msg);	sem_post(&glob_mgr->new_msg);  	return 0;   ERR:	return -1; }int manager_isdn_handler(iframe_t *frm ,msg_t *msg){  	if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM)) {		printf("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");	}	if (handle_timers(msg)) 		return 0 ;    	if (handle_mgmt(msg)) 		return 0 ;	if (handle_l2(msg)) 		return 0 ;	/* Its important to handle l1 AFTER l2  */	if (handle_l1(msg)) 		return 0 ;	if (handle_bchan(msg)) 		return 0 ;	/** Handle L2/3 Signalling after bchans **/ 	if (handle_frm_nt(msg)) 		return 0 ;    	if (handle_frm(msg)) 		return 0 ;	cb_log(0, frm->addr&IF_CONTRMASK, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on port: %d\n",frm->prim, frm->len, frm->addr, frm->dinfo, frm->addr&IF_CONTRMASK);   	free_msg(msg);	return 0;}int misdn_lib_get_port_info(int port){	msg_t *msg=alloc_msg(MAX_MSG_SIZE);	iframe_t *frm;	struct misdn_stack *stack=find_stack_by_port(port);	if (!msg) {		cb_log(0, port, "misgn_lib_get_port: alloc_msg failed!\n");		return -1;	}	frm=(iframe_t*)msg->data;	if (!stack ) {		cb_log(0, port, "There is no Stack on Port:%d\n",port);		return -1;	}	/* activate bchannel */	frm->prim = CC_STATUS_ENQUIRY | REQUEST;	frm->addr = stack->upper_id;	frm->dinfo = 0;	frm->len = 0;  	msg_queue_tail(&glob_mgr->activatequeue, msg);	sem_post(&glob_mgr->new_msg);  	return 0; }int misdn_lib_port_restart(int port){	struct misdn_stack *stack=find_stack_by_port(port); 	cb_log(0, port, "Restarting Port:%d\n",port);	if (stack) {		cb_log(0, port, "Stack:%p\n",stack);				clear_l3(stack);				{			msg_t *msg=alloc_msg(MAX_MSG_SIZE);			iframe_t *frm;			if (!msg) {				cb_log(0, port, "port_restart: alloc_msg fialed\n");				return -1;			}						frm=(iframe_t*)msg->data;			/* we must activate if we are deactivated */			/* activate bchannel */				frm->prim = DL_RELEASE | REQUEST;				frm->addr = stack->upper_id ;			frm->dinfo = 0;			frm->len = 0;			msg_queue_tail(&glob_mgr->activatequeue, msg);			sem_post(&glob_mgr->new_msg);		}		return 0;    		stack_te_destroy(stack);      		{			struct misdn_stack *tmpstack;			struct misdn_stack *newstack=stack_te_init(stack->midev ,port, stack->ptp);            			if (stack == glob_mgr->stack_list) {				struct misdn_stack *n=glob_mgr->stack_list->next;				glob_mgr->stack_list = newstack ;				glob_mgr->stack_list->next = n;			} else {				for (tmpstack=glob_mgr->stack_list;				     tmpstack->next;				     tmpstack=tmpstack->next) 					if (tmpstack->next == stack) break;				if (!tmpstack->next) {					cb_log(0, port, "Stack to restart not found\n");					return 0;				}  else {					struct misdn_stack *n=tmpstack->next->next;					tmpstack->next=newstack;					newstack->next=n;				}			}      			{				int i;				for(i=0;i<newstack->b_num; i++) {					int r;					if ((r=init_bc(newstack, &newstack->bc[i], newstack->midev,port,i, "", 1))<0) {						cb_log(0, port, "Got Err @ init_bc :%d\n",r);						return 0;					}				}			}      			free(stack);		}	}	return 0;}sem_t handler_started; void manager_event_handler(void *arg){	sem_post(&handler_started); 	while (1) {		struct misdn_stack *stack;		msg_t *msg;    		/** wait for events **/		sem_wait(&glob_mgr->new_msg);    		for (msg=msg_dequeue(&glob_mgr->activatequeue);		     msg;		     msg=msg_dequeue(&glob_mgr->activatequeue)			)		{				iframe_t *frm =  (iframe_t*) msg->data ;			switch ( frm->prim) {			case MGR_SETSTACK | REQUEST :				break;			default:				mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);				free_msg(msg);			}		}		for (stack=glob_mgr->stack_list;		     stack;		     stack=stack->next ) { 			while ( (msg=msg_dequeue(&stack->downqueue)) ) {					if (stack->mode == NT_MODE ){	  					if (stack->nst.manager_l3(&stack->nst, msg))						cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n");	  				} else {					if (msg) {						iframe_t *frm = (iframe_t *)msg->data;						struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);	    						if (bc) send_msg(glob_mgr->midev, bc, msg);					}				}			}		}	}}int misdn_lib_maxports_get() { /** BE AWARE WE HAVE NO CB_LOG HERE! **/		int i = mISDN_open();	int max=0;		if (i<0)		return -1;	max = mISDN_get_stack_count(i);		mISDN_close(i);		return max;}int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_data){	struct misdn_lib *mgr=calloc(1, sizeof(struct misdn_lib));	char *tok, *tokb;	char plist[1024];	int midev;	int port_count=0; 	cb_log = iface->cb_log;	cb_event = iface->cb_event;	cb_clearl3_true = iface->cb_clearl3_true;		glob_mgr = mgr;  	msg_init();	debug_init(0 , NULL, NULL, NULL);		if (!portlist || (*portlist == 0) ) return 1;		init_flip_bits();		{		strncpy(plist,portlist, 1024);		plist[1023] = 0;	}  	memcpy(tone_425_flip,tone_425,TONE_425_SIZE);	flip_buf_bits(tone_425_flip,TONE_425_SIZE);	memcpy(tone_silence_flip,tone_SILENCE,TONE_SILENCE_SIZE);	flip_buf_bits(tone_silence_flip,TONE_SILENCE_SIZE);  	midev=te_lib_init();	mgr->midev=midev;	port_count=mISDN_get_stack_count(midev);  	msg_queue_init(&mgr->activatequeue);  	if (sem_init(&mgr->new_msg, 1, 0)<0)		sem_init(&mgr->new_msg, 0, 0);  	for (tok=strtok_r(plist," ,",&tokb );	     tok; 	     tok=strtok_r(NULL," ,",&tokb)) {		int port = atoi(tok);		struct misdn_stack *stack;		static int first=1;		int ptp=0;    		if (strstr(tok, "ptp"))			ptp=1;		if (port > port_count) {			cb_log(0, port, "Couldn't Initialize Port:%d since we have only %d ports\n",port, port_count);			exit(1);		}		stack=stack_te_init(midev, port, ptp);            		if (!stack) {			perror("init_stack");			exit(1);		}    		if (stack && first) {			mgr->stack_list=stack;			first=0;			{				int i;				for(i=0;i<stack->b_num; i++) {					int r;					if ((r=init_bc(stack, &stack->bc[i], stack->midev,port,i, "", 1))<0) {						cb_log(0, port, "Got Err @ init_bc :%d\n",r);						exit(1);					}				}			}      			continue;		}    		if (stack) {			struct misdn_stack * help;			for ( help=mgr->stack_list; help; help=help->next ) 				if (help->next == NULL) break;            			help->next=stack;			{				int i;				for(i=0;i<stack->b_num; i++) {					int r;					if ((r=init_bc(sta

⌨️ 快捷键说明

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