diff options
author | crichter <crichter@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-04-29 22:56:00 +0000 |
---|---|---|
committer | crichter <crichter@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-04-29 22:56:00 +0000 |
commit | abdc0b971040c6956d8c249e09822cf967419542 (patch) | |
tree | f7730551c036f3c73a7b9a3513314e1c6111447c | |
parent | a2120a0a67756bad560f19b714544663875641d2 (diff) |
added an up-queue message mechanism to avoid buffer fillups in the kernel, also changed some strdups to ast_strdupa
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@23443 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | channels/chan_misdn.c | 59 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.c | 110 | ||||
-rw-r--r-- | channels/misdn/isdn_lib_intern.h | 1 |
3 files changed, 131 insertions, 39 deletions
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index ae4c5ce69..1b307721a 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -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); } { diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index 627cccaee..824fc59cd 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -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); } } diff --git a/channels/misdn/isdn_lib_intern.h b/channels/misdn/isdn_lib_intern.h index 5e9e56539..8a964313c 100644 --- a/channels/misdn/isdn_lib_intern.h +++ b/channels/misdn/isdn_lib_intern.h @@ -74,6 +74,7 @@ struct misdn_stack { int procids[0x100+1]; msg_queue_t downqueue; + msg_queue_t upqueue; int busy; int port; |