mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	added an up-queue message mechanism to avoid buffer fillups in the kernel, also changed some strdups to ast_strdupa
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@23443 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -183,6 +183,9 @@ struct chan_list { | ||||
|  | ||||
| 	char context[BUFFERSIZE]; | ||||
|  | ||||
| 	int zero_read_cnt; | ||||
| 	int dropped_frame_cnt; | ||||
|  | ||||
| 	const struct tone_zone_sound *ts; | ||||
| 	 | ||||
| 	struct chan_list *peer; | ||||
| @@ -749,7 +752,7 @@ static int misdn_set_tics (int fd, int argc, char *argv[]) | ||||
| static int misdn_show_stacks (int fd, int argc, char *argv[]) | ||||
| { | ||||
| 	int port; | ||||
| 	 | ||||
|  | ||||
| 	ast_cli(fd, "BEGIN STACK_LIST:\n"); | ||||
|  | ||||
| 	for (port=misdn_cfg_get_next_port(0); port > 0; | ||||
| @@ -927,7 +930,7 @@ static char *complete_ch_helper(const char *line, const char *word, int pos, int | ||||
| 		c = ast_channel_walk_locked(c); | ||||
| 	} | ||||
| 	if (c) { | ||||
| 		ret = strdup(c->name); | ||||
| 		ret = ast_strdupa(c->name); | ||||
| 		ast_mutex_unlock(&c->lock); | ||||
| 	} else | ||||
| 		ret = NULL; | ||||
| @@ -946,12 +949,12 @@ static char *complete_debug_port (const char *line, const char *word, int pos, i | ||||
|  | ||||
| 	switch (pos) { | ||||
| 	case 4: if (*word == 'p') | ||||
| 				return strdup("port"); | ||||
| 				return ast_strdupa("port"); | ||||
| 			else if (*word == 'o') | ||||
| 				return strdup("only"); | ||||
| 				return ast_strdupa("only"); | ||||
| 			break; | ||||
| 	case 6: if (*word == 'o') | ||||
| 				return strdup("only"); | ||||
| 				return ast_strdupa("only"); | ||||
| 			break; | ||||
| 	} | ||||
| 	return NULL; | ||||
| @@ -1504,17 +1507,13 @@ static int read_config(struct chan_list *ch, int orig) { | ||||
| 		if ( strcmp(bc->dad,ast->exten)) { | ||||
| 			ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten)); | ||||
| 		} | ||||
| 		if ( ast->cid.cid_num && strcmp(ast->cid.cid_num, bc->oad)) { | ||||
| 			free(ast->cid.cid_num); | ||||
| 			ast->cid.cid_num=NULL; | ||||
| 			 | ||||
| 		} | ||||
| 		 | ||||
| 		if ( !ast->cid.cid_num) { | ||||
| 			ast->cid.cid_num=strdup(bc->oad); | ||||
| 			ast_set_callerid(ast, bc->oad, NULL, bc->oad); | ||||
| 		} | ||||
| 		 | ||||
| 		if ( !ast_strlen_zero(bc->rad) )  | ||||
| 			ast->cid.cid_rdnis=strdup(bc->rad); | ||||
| 			ast->cid.cid_rdnis=ast_strdupa(bc->rad); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| @@ -2062,10 +2061,20 @@ static struct ast_frame  *misdn_read(struct ast_channel *ast) | ||||
| 	len = misdn_ibuf_usedcount(tmp->bc->astbuf); | ||||
|  | ||||
| 	if (!len) { | ||||
| 		chan_misdn_log(4,tmp->bc->port,"misdn_read: ZERO READ\n"); | ||||
| 		struct ast_frame *frame; | ||||
| 		if(!tmp->zero_read_cnt) | ||||
| 			chan_misdn_log(4,tmp->bc->port,"misdn_read: ZERO READ\n"); | ||||
| 		tmp->zero_read_cnt++; | ||||
|  | ||||
| 		if (tmp->zero_read_cnt > 5000) { | ||||
| 			chan_misdn_log(4,tmp->bc->port,"misdn_read: ZERO READ counted > 5000 times\n"); | ||||
| 			tmp->zero_read_cnt=0; | ||||
|  | ||||
| 		} | ||||
| 		tmp->frame.frametype = AST_FRAME_NULL; | ||||
| 		tmp->frame.subclass = 0; | ||||
| 		return &tmp->frame; | ||||
| 		frame=ast_frisolate(&tmp->frame); | ||||
| 		return frame; | ||||
| 	} | ||||
|  | ||||
| 	/*shrinken len if necessary, we transmit at maximum 4k*/ | ||||
| @@ -2154,7 +2163,16 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame) | ||||
| 		case BCHAN_BRIDGED: | ||||
| 			break; | ||||
| 		default: | ||||
| 		chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch)); | ||||
| 		if (!ch->dropped_frame_cnt) | ||||
| 			chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state); | ||||
| 		 | ||||
| 		ch->dropped_frame_cnt++; | ||||
| 		if (ch->dropped_frame_cnt > 100) { | ||||
| 			ch->dropped_frame_cnt=0; | ||||
| 			chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x  dropped > 100 frames!\n",frame->samples,ch->bc->addr); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		return 0; | ||||
| 	} | ||||
| 	 | ||||
| @@ -2264,10 +2282,6 @@ static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0, | ||||
|      | ||||
| 	} | ||||
|    | ||||
| 	if (bridging) { | ||||
| 		misdn_lib_split_bridge(ch1->bc,ch2->bc); | ||||
| 	} | ||||
|    | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -2612,10 +2626,9 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char | ||||
| 			char *cid_name, *cid_num; | ||||
|        | ||||
| 			ast_callerid_parse(callerid, &cid_name, &cid_num); | ||||
| 			if (cid_name) | ||||
| 				tmp->cid.cid_name=strdup(cid_name); | ||||
| 			if (cid_num) | ||||
| 				tmp->cid.cid_num=strdup(cid_num); | ||||
| 			ast_set_callerid(tmp, cid_num,cid_name,cid_num); | ||||
| 		} else { | ||||
| 			ast_set_callerid(tmp, NULL,NULL,NULL); | ||||
| 		} | ||||
|  | ||||
| 		{ | ||||
|   | ||||
| @@ -802,6 +802,8 @@ static int create_process (int midev, struct misdn_bchannel *bc) { | ||||
| 		free_chan = find_free_chan_in_stack(stack, bc->channel_preselected?bc->channel:0); | ||||
| 		if (!free_chan) return -1; | ||||
| 		bc->channel=free_chan; | ||||
| 		 | ||||
| 		cb_log(0,stack->port, " -->  found channel: %d\n",free_chan); | ||||
|      | ||||
| 		for (i=0; i <= MAXPROCS; i++) | ||||
| 			if (stack->procids[i]==0) break; | ||||
| @@ -833,6 +835,7 @@ static int create_process (int midev, struct misdn_bchannel *bc) { | ||||
| 			free_chan = find_free_chan_in_stack(stack, bc->channel_preselected?bc->channel:0); | ||||
| 			if (!free_chan) return -1; | ||||
| 			bc->channel=free_chan; | ||||
| 			cb_log(0,stack->port, " -->  found channel: %d\n",free_chan); | ||||
| 		} else { | ||||
| 			/* other phones could have made a call also on this port (ptmp) */ | ||||
| 			bc->channel=0xff; | ||||
| @@ -1107,6 +1110,7 @@ struct misdn_stack* stack_init( int midev, int port, int ptp ) | ||||
| 	stack->pri=0; | ||||
|    | ||||
| 	msg_queue_init(&stack->downqueue); | ||||
| 	msg_queue_init(&stack->upqueue); | ||||
|    | ||||
| 	/* query port's requirements */ | ||||
| 	ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff)); | ||||
| @@ -2072,11 +2076,18 @@ int handle_bchan(msg_t *msg) | ||||
| 		 | ||||
| 	case MGR_SETSTACK| INDICATION: | ||||
| 		cb_log(2, stack->port, "BCHAN: MGR_SETSTACK|IND \n"); | ||||
| 		 | ||||
|  | ||||
| 	AGAIN: | ||||
| 		bc->addr = mISDN_get_layerid(stack->midev, bc->b_stid, bc->layer); | ||||
| 		if (!bc->addr) { | ||||
| 			cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno)); | ||||
|  | ||||
| 			if (errno == EAGAIN) { | ||||
| 				usleep(1000); | ||||
| 				goto AGAIN; | ||||
| 			} | ||||
| 			 | ||||
| 			cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno)); | ||||
| 			 | ||||
| 			/* we kill the channel later, when we received some | ||||
| 			   data. */ | ||||
| 			bc->addr= frm->addr; | ||||
| @@ -2587,10 +2598,12 @@ msg_t *fetch_msg(int midev) | ||||
| 	FD_SET(midev,&rdfs); | ||||
|    | ||||
| 	mISDN_select(FD_SETSIZE, &rdfs, NULL, NULL, NULL); | ||||
| 	//select(FD_SETSIZE, &rdfs, NULL, NULL, NULL); | ||||
|    | ||||
| 	if (FD_ISSET(midev, &rdfs)) { | ||||
|      | ||||
| 		r=mISDN_read(midev,msg->data,MAX_MSG_SIZE,0); | ||||
|  | ||||
| 	AGAIN: | ||||
| 		r=mISDN_read(midev,msg->data,MAX_MSG_SIZE, 5000); | ||||
| 		msg->len=r; | ||||
|      | ||||
| 		if (r==0) { | ||||
| @@ -2599,6 +2612,17 @@ msg_t *fetch_msg(int midev) | ||||
| 			return NULL; | ||||
| 		} | ||||
|  | ||||
| 		if (r<0) { | ||||
| 			if (errno == EAGAIN) { | ||||
| 				/*we wait for mISDN here*/ | ||||
| 				cb_log(-1,0,"mISDN_read wants us to wait\n"); | ||||
| 				usleep(5000); | ||||
| 				goto AGAIN; | ||||
| 			} | ||||
| 			 | ||||
| 			cb_log(-1,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno);  | ||||
| 		} | ||||
|  | ||||
| 		return msg; | ||||
| 	} else { | ||||
| 		printf ("Select timeout\n"); | ||||
| @@ -2976,6 +3000,22 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) | ||||
| int handle_err(msg_t *msg) | ||||
| { | ||||
| 	iframe_t *frm = (iframe_t*) msg->data; | ||||
|  | ||||
|  | ||||
| 	if (!frm->addr) { | ||||
| 		static int cnt=0; | ||||
| 		if (!cnt) | ||||
| 			cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x\n",frm->prim,frm->dinfo); | ||||
| 		cnt++; | ||||
| 		if (cnt>100) { | ||||
| 			cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x (already more than 100 of them)\n",frm->prim,frm->dinfo); | ||||
| 			cnt=0; | ||||
| 		} | ||||
| 		 | ||||
| 		free_msg(msg); | ||||
| 		return 1; | ||||
| 		 | ||||
| 	} | ||||
| 	 | ||||
| 	switch (frm->prim) { | ||||
| 		case DL_DATA|INDICATION: | ||||
| @@ -2983,7 +3023,13 @@ int handle_err(msg_t *msg) | ||||
| 			int port=(frm->addr&MASTER_ID_MASK) >> 8; | ||||
| 			int channel=(frm->addr&CHILD_ID_MASK) >> 16; | ||||
|  | ||||
| 			cb_log(3,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel); | ||||
| 			/*we flush the read buffer here*/ | ||||
| 			 | ||||
| 			cb_log(9,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel); | ||||
| 			 | ||||
| 			free_msg(msg) ;  | ||||
| 			return 1; | ||||
| 			 | ||||
| 			 | ||||
| 			struct misdn_bchannel *bc=find_bc_by_channel( port , channel); | ||||
|  | ||||
| @@ -3015,11 +3061,28 @@ int handle_err(msg_t *msg) | ||||
| } | ||||
|  | ||||
|  | ||||
| int queue_l2l3(msg_t *msg) { | ||||
| 	iframe_t *frm= (iframe_t*)msg->data; | ||||
| 	struct misdn_stack *stack; | ||||
| 	int err=0; | ||||
|  | ||||
| 	stack=find_stack_by_addr( frm->addr ); | ||||
|  | ||||
| 	 | ||||
| 	if (!stack) { | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	msg_queue_tail(&stack->upqueue, msg); | ||||
| 	sem_post(&glob_mgr->new_msg); | ||||
| 	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"); | ||||
| 		cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n"); | ||||
| 	} | ||||
|  | ||||
| 	if ( ((frm->addr | ISDN_PID_BCHANNEL_BIT )>> 28 ) == 0x5) { | ||||
| @@ -3039,21 +3102,17 @@ int manager_isdn_handler(iframe_t *frm ,msg_t *msg) | ||||
| 	/* Its important to handle l1 AFTER l2  */ | ||||
| 	if (handle_l1(msg))  | ||||
| 		return 0 ; | ||||
| 	 | ||||
| 	 | ||||
| 	/** Handle L2/3 Signalling after bchans **/  | ||||
| 	if (handle_frm_nt(msg))  | ||||
| 		return 0 ; | ||||
| 	 | ||||
| 	if (handle_frm(msg))  | ||||
| 		return 0 ; | ||||
|  | ||||
| 	/* The L2/L3 will be queued */ | ||||
| 	if (queue_l2l3(msg)) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (handle_err(msg))  | ||||
| 		return 0 ; | ||||
| 	 | ||||
|  | ||||
| 	cb_log(-1, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);		 | ||||
|     | ||||
| 	free_msg(msg); | ||||
| 	 | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
| @@ -3200,6 +3259,24 @@ void manager_event_handler(void *arg) | ||||
| 		for (stack=glob_mgr->stack_list; | ||||
| 		     stack; | ||||
| 		     stack=stack->next ) {  | ||||
|  | ||||
| 			while ( (msg=msg_dequeue(&stack->upqueue)) ) { | ||||
| 				int res=0; | ||||
| 				/** Handle L2/3 Signalling after bchans **/  | ||||
| 				if (!handle_frm_nt(msg)) { | ||||
| 					/* Maybe it's TE */ | ||||
| 					if (!handle_frm(msg)) { | ||||
| 						/* wow none! */ | ||||
| 						cb_log(-1,stack->port,"Wow we've got a strange issue while dequeueing a Frame\n"); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			/* Here we should check if we really want to  | ||||
| 				send all the messages we've queued, lets  | ||||
| 				assume we've queued a Disconnect, but  | ||||
| 				received it already from the other side!*/ | ||||
| 		      | ||||
| 			while ( (msg=msg_dequeue(&stack->downqueue)) ) { | ||||
| 				if (stack->nt ) { | ||||
| 					if (stack->nst.manager_l3(&stack->nst, msg)) | ||||
| @@ -3208,6 +3285,7 @@ void manager_event_handler(void *arg) | ||||
| 				} else { | ||||
| 					iframe_t *frm = (iframe_t *)msg->data; | ||||
| 					struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo); | ||||
| 					cb_log(0,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo); | ||||
| 					if (bc) send_msg(glob_mgr->midev, bc, msg); | ||||
| 				} | ||||
| 			} | ||||
|   | ||||
| @@ -74,6 +74,7 @@ struct misdn_stack { | ||||
| 	int procids[0x100+1]; | ||||
|  | ||||
| 	msg_queue_t downqueue; | ||||
| 	msg_queue_t upqueue; | ||||
| 	int busy; | ||||
|    | ||||
| 	int port; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user