From 169754edd213a86e474125432efd89ce632478d5 Mon Sep 17 00:00:00 2001 From: crichter Date: Tue, 6 Jun 2006 09:40:41 +0000 Subject: added select before write to avoid deadlock on full buffer. added some defines for deadlock debugging. added code snippet for generating silence if we don't have data to write. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@32524 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_misdn.c | 37 +++++++++++--- channels/misdn/isdn_lib.c | 123 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 139 insertions(+), 21 deletions(-) (limited to 'channels') diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index aa1207ceb..4631fa5e6 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -2352,7 +2352,6 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone) break; case TONE_FILE: break; - case TONE_NONE: chan_misdn_log(3,cl->bc->port," --> None\n"); misdn_lib_tone_generator_stop(cl->bc); @@ -3285,7 +3284,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ast_queue_frame(ch->ast, &fr); } - } } break; @@ -3694,7 +3692,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples); chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n"); - + if (!ast->generator) break; tmp = ast->generatordata; @@ -3702,13 +3700,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) generate = ast->generator->generate; res = generate(ast, tmp, tone_len, tone_len); ast->generatordata = tmp; + if (res) { ast_log(LOG_WARNING, "Auto-deactivating generator\n"); ast_deactivate_generator(ast); } else { bc->tone_cnt=0; } - } break; @@ -3728,10 +3726,35 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ast_queue_frame(ch->ast,&frame); } else { - int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len); + fd_set wrfs; + struct timeval tv; + tv.tv_sec=0; + tv.tv_usec=0; + + + FD_ZERO(&wrfs); + FD_SET(ch->pipe[1],&wrfs); + + int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv); - if (ret<=0) { - chan_misdn_log(1, bc->port, "Write returned <=0 (err=%s)\n",strerror(errno)); + if (!t) { + chan_misdn_log(9, bc->port, "Select Timed out\n"); + break; + } + + if (t<0) { + chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno)); + break; + } + + if (FD_ISSET(ch->pipe[1],&wrfs)) { + int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len); + + if (ret<=0) { + chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s)\n",strerror(errno)); + } + } else { + chan_misdn_log(1, bc->port, "Wripe Pipe full!\n"); } } } diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index 9f23930db..a53b573eb 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -599,7 +599,7 @@ int clean_up_bc(struct misdn_bchannel *bc) cb_log(3, stack->port, "$$$ CLEARING STACK\n"); ret=mISDN_clear_stack(stack->midev,bc->b_stid); - if (ret<0) { + if (ret<0 && errno) { cb_log(-1,stack->port,"clear stack failed [%s]\n",strerror(errno)); } @@ -1986,7 +1986,7 @@ static int do_tone(struct misdn_bchannel *bc, int len) if (bc->generate_tone) { cb_event(EVENT_TONE_GENERATE, bc, glob_mgr->user_data); - + if ( !bc->nojitter ) { misdn_tx_jitter(bc,len); } @@ -2002,13 +2002,14 @@ static int do_tone(struct misdn_bchannel *bc, int len) void misdn_tx_jitter(struct misdn_bchannel *bc, int len) { char buf[4096 + mISDN_HEADER_LEN]; + char *data=&buf[mISDN_HEADER_LEN]; iframe_t *txfrm= (iframe_t*)buf; int jlen, r; - jlen=cb_jb_empty(bc,&buf[mISDN_HEADER_LEN],len); + jlen=cb_jb_empty(bc,data,len); if (jlen) { - flip_buf_bits( &buf[mISDN_HEADER_LEN], jlen); + flip_buf_bits( data, jlen); if (jlen < len) { cb_log(5,bc->port,"Jitterbuffer Underrun.\n"); @@ -2024,6 +2025,33 @@ void misdn_tx_jitter(struct misdn_bchannel *bc, int len) cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len); r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 ); + } else { +#ifdef MISDN_GEN_SILENCE + int cnt=len/TONE_SILENCE_SIZE; + int rest=len%TONE_SILENCE_SIZE; + int i; + + for (i=0; iprim = DL_DATA|REQUEST; + + txfrm->dinfo = 0; + + txfrm->addr = bc->addr|FLG_MSG_DOWN; /* | IF_DOWN; */ + + txfrm->len =len; + cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len); + + r=mISDN_write( glob_mgr->midev, buf, txfrm->len + mISDN_HEADER_LEN, 8000 ); +#endif + } } @@ -2201,15 +2229,39 @@ int handle_bchan(msg_t *msg) #endif if ( (bc->bc_state == BCHAN_ACTIVATED) && frm->len > 0) { - if ( !do_tone(bc, frm->len) ) { + int t; + +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"do_tone START\n"); +#endif + t=do_tone(bc,frm->len); + +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"do_tone STOP (%d)\n",t); +#endif + if ( !t ) { if ( misdn_cap_is_speech(bc->capability)) { if ( !bc->nojitter ) { +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"tx_jitter START\n"); +#endif misdn_tx_jitter(bc,frm->len); +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"tx_jitter STOP\n"); +#endif } } + +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"EVENT_B_DATA START\n"); +#endif int i=cb_event( EVENT_BCHAN_DATA, bc, glob_mgr->user_data); +#ifdef MISDN_B_DEBUG + cb_log(0,bc->port,"EVENT_B_DATA STOP\n"); +#endif + if (i<0) { cb_log(10,stack->port,"cb_event returned <0\n"); /*clean_up_bc(bc);*/ @@ -2262,7 +2314,8 @@ int handle_frm_nt(msg_t *msg) if (!stack || !stack->nt) { return 0; } - + + if ((err=stack->nst.l1_l2(&stack->nst,msg))) { if (nt_err_cnt > 0 ) { @@ -2520,6 +2573,8 @@ int handle_mgmt(msg_t *msg) case SSTATUS_L1_DEACTIVATED: cb_log(1, 0, "MGMT: SSTATUS: L1_DEACTIVATED \n"); stack->l1link=0; + + clear_l3(stack); break; case SSTATUS_L2_ESTABLISHED: @@ -3096,10 +3151,20 @@ int manager_isdn_handler(iframe_t *frm ,msg_t *msg) } if ( ((frm->addr | ISDN_PID_BCHANNEL_BIT )>> 28 ) == 0x5) { - if (handle_bchan(msg)) +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_bchan START\n"); +#endif + if (handle_bchan(msg)) { +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_bchan STOP\n"); +#endif return 0 ; + } +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_bchan NOTSTOP\n"); +#endif } - + if (handle_timers(msg)) return 0 ; @@ -3112,16 +3177,46 @@ int manager_isdn_handler(iframe_t *frm ,msg_t *msg) /* Its important to handle l1 AFTER l2 */ if (handle_l1(msg)) return 0 ; - - if (handle_frm_nt(msg)) + +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_frm_nt START\n"); +#endif + if (handle_frm_nt(msg)) { +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_frm_nt STOP\n"); +#endif return 0; - - if (handle_frm(msg)) + } +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_frm_nt NOTSTOP\n"); + + cb_log(0,0,"handle_frm START\n"); +#endif + + if (handle_frm(msg)) { +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_frm STOP\n"); +#endif + return 0; - - if (handle_err(msg)) + } +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_frm NOTSTOP\n"); + + cb_log(0,0,"handle_err START\n"); +#endif + + if (handle_err(msg)) { +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_err STOP\n"); +#endif return 0 ; + } +#ifdef MISDN_HANDLER_DEBUG + cb_log(0,0,"handle_err NOTSTOP\n"); +#endif + 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); -- cgit v1.2.3