diff options
author | crichter <crichter@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-06-17 10:37:35 +0000 |
---|---|---|
committer | crichter <crichter@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-06-17 10:37:35 +0000 |
commit | 198718ea0a36b43039278a6ea0ffc9ce40f6150f (patch) | |
tree | f6bf90b6a3ced4c91c681b129c1182ea45bd3ddc /channels | |
parent | 2bcb71214f83c4aa42fa534910d650066b34bb0d (diff) |
* fixed bchannel cleaning race condition with new bchannel state (CLEAN_REQUEST)
* added early bridge-hook, so we know if we need to generate ringing or
can take it from the far end chan_misdn channel (if available)
* fixed the issue, that we may not activate the bchannel on PTMP,
when we receive ALERTING/PROCEEDING/PROGRESS, only on CONNECT. There might
be other PTMP devices and we might disturb their bchannel.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@34552 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_misdn.c | 178 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.c | 55 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.h | 1 |
3 files changed, 153 insertions, 81 deletions
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 4e6270a60..de28d5106 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -88,8 +88,6 @@ struct misdn_jb{ ast_mutex_t mutexjb; }; -void export_ies(struct ast_channel *chan, struct misdn_bchannel *bc); -void import_ies(struct ast_channel *chan, struct misdn_bchannel *bc); /* allocates the jb-structure and initialise the elements*/ @@ -185,6 +183,8 @@ struct chan_list { struct ast_trans_pvt *trans; struct ast_channel * ast; + + int dummy; struct misdn_bchannel *bc; struct misdn_bchannel *holded_bc; @@ -198,6 +198,8 @@ struct chan_list { int dropped_frame_cnt; int far_alerting; + int other_pid; + struct chan_list *other_ch; const struct tone_zone_sound *ts; @@ -207,6 +209,11 @@ struct chan_list { struct chan_list *first; }; + + +void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch); +void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch); + struct robin_list { char *group; int port; @@ -306,6 +313,7 @@ static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc); static void cl_queue_chan(struct chan_list **list, struct chan_list *chan); static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan); static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc); +static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid); @@ -1638,7 +1646,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout) update_config(ch,ORG_AST); /* fill in some ies from channel vary*/ - import_ies(ast, newbc); + import_ch(ast, newbc, ch); /* Finally The Options Override Everything */ if (opts) @@ -1854,7 +1862,12 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data, p->state=MISDN_ALERTING; chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1); misdn_lib_send_event( p->bc, EVENT_ALERTING); - + + if (p->other_ch && p->other_ch->bc && misdn_inband_avail(p->other_ch->bc)) { + chan_misdn_log(1,p->bc->port, " --> other End is mISDN and has inband info available\n"); + break; + } + if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio ) chan_misdn_log(1,p->bc->port, " --> incoming_early_audio off\n"); else @@ -1902,10 +1915,11 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data, case -1 : chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1); - if (p->state == MISDN_CONNECTED) + tone_indicate(p, TONE_NONE); + + if (p->state == MISDN_CONNECTED) start_bc_tones(p); - else - tone_indicate(p, TONE_NONE); + break; case AST_CONTROL_HOLD: @@ -1996,8 +2010,11 @@ static int misdn_hangup(struct ast_channel *ast) start_bc_tones(p); tone_indicate(p, TONE_BUSY); p->state=MISDN_CLEANING; - - misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE); + + if (bc->nt) + misdn_lib_send_event( bc, EVENT_RELEASE); + else + misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE); break; @@ -2349,7 +2366,15 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone) chan_misdn_log(3,cl->bc->port,"Tone Indicate:\n"); if (!cl->ast) { + chan_misdn_log(-1,cl->bc->port,"Ast Ptr Not existing anymore.. we need to generate tones ourselves now (tbd)\n"); return 0; +#if 0 + struct ast_channel *dummy=misdn_new(cl, AST_STATE_RESERVED, cl->bc->dad, cl->bc->oad, AST_FORMAT_ALAW, cl->bc->port, 99); + cl->ast=dummy; + /* return 0; */ + cl->dummy=1; + ast=cl->ast; +#endif } switch (tone) { @@ -2361,7 +2386,7 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone) case TONE_ALERTING: chan_misdn_log(3,cl->bc->port," --> Ring\n"); ts=ast_get_indication_tone(ast->zone,"ring"); - misdn_lib_tone_generator_stop(cl->bc); + misdn_lib_tone_generator_start(cl->bc); break; case TONE_FAR_ALERTING: /* VERY UGLY HACK, BECAUSE CHAN_SIP DOES NOT GENERATE TONES */ @@ -2373,7 +2398,7 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone) case TONE_BUSY: chan_misdn_log(3,cl->bc->port," --> Busy\n"); ts=ast_get_indication_tone(ast->zone,"busy"); - misdn_lib_tone_generator_stop(cl->bc); + misdn_lib_tone_generator_start(cl->bc); break; case TONE_FILE: break; @@ -2460,7 +2485,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat chan_misdn_log(2, 0, " --> Group Call group: %s\n",group); } else if ((p = strchr(port_str, ':'))) { - // we have a preselected channel + /* we have a preselected channel */ *p = 0; channel = atoi(++p); port = atoi(port_str); @@ -2748,6 +2773,17 @@ static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bc return NULL; } +static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid) +{ + struct chan_list *help=list; + for (;help; help=help->next) { + if (help->bc->pid == pid) return help; + } + + chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid); + + return NULL; +} static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc) { @@ -2839,8 +2875,15 @@ static void release_chan(struct misdn_bchannel *bc) { release_unlock; chan_misdn_log(1, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id); +#if 0 + if (ch->dummy) { + ast_hangup(ast); + ch->ast=NULL; + ast=NULL; + } +#endif - //releaseing jitterbuffer + /*releaseing jitterbuffer*/ if (ch->jb ) { misdn_jb_destroy(ch->jb); ch->jb=NULL; @@ -3042,47 +3085,31 @@ static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) { } } -void import_ies(struct ast_channel *chan, struct misdn_bchannel *bc) -{ - const char *tmp; - - tmp=pbx_builtin_getvar_helper(chan,"PRI_MODE"); - if (tmp) bc->mode=atoi(tmp); - tmp=pbx_builtin_getvar_helper(chan,"PRI_URATE"); - if (tmp) bc->urate=atoi(tmp); - tmp=pbx_builtin_getvar_helper(chan,"PRI_RATE"); - if (tmp) bc->rate=atoi(tmp); - tmp=pbx_builtin_getvar_helper(chan,"PRI_USER1"); - if (tmp) bc->user1=atoi(tmp); - - tmp=pbx_builtin_getvar_helper(chan,"PRI_PROGRESS_INDICATOR"); - if (tmp) bc->progress_indicator=atoi(tmp); +void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch) +{ + char *tmp; + tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID"); + if (tmp) { + ch->other_pid=atoi(tmp); + chan_misdn_log(1,bc->port,"IMPORT_PID: importing pid:%s\n",tmp); + if (ch->other_pid >0) { + ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid); + if (ch->other_ch) ch->other_ch->other_ch=ch; + } + } } -void export_ies(struct ast_channel *chan, struct misdn_bchannel *bc) +void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch) { char tmp[32]; - - sprintf(tmp,"%d",bc->mode); - pbx_builtin_setvar_helper(chan,"_PRI_MODE",tmp); - - sprintf(tmp,"%d",bc->urate); - pbx_builtin_setvar_helper(chan,"_PRI_URATE",tmp); - - sprintf(tmp,"%d",bc->rate); - pbx_builtin_setvar_helper(chan,"_PRI_RATE",tmp); - - sprintf(tmp,"%d",bc->user1); - pbx_builtin_setvar_helper(chan,"_PRI_USER1",tmp); - - sprintf(tmp,"%d",bc->progress_indicator); - pbx_builtin_setvar_helper(chan,"_PRI_PROGRESS_INDICATOR",tmp); + chan_misdn_log(1,bc->port,"EXPORT_PID: pid:%d\n",bc->pid); + sprintf(tmp,"%d",bc->pid); + pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp); } - int add_in_calls(int port) { int max_in_calls; @@ -3145,9 +3172,12 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) if (ch ) { switch (event) { + case EVENT_DISCONNECT: case EVENT_RELEASE: case EVENT_RELEASE_COMPLETE: case EVENT_CLEANUP: + case EVENT_TIMEOUT: + chan_misdn_log(3,bc->port,"ast_hangup already called, so we have no ast ptr anymore in event(%s)\n",manager_isdn_get_info(event)); break; default: if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) { @@ -3357,8 +3387,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) read_config(ch, ORG_MISDN); - export_ies(chan, bc); - + export_ch(chan, bc, ch); + ch->ast->rings=1; ast_setstate(ch->ast, AST_STATE_RINGING); @@ -3483,10 +3513,18 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } } else { - if (bc->sending_complete) { + ch->state=MISDN_EXTCANTMATCH; bc->out_cause=1; - misdn_lib_send_event(bc, EVENT_RELEASE); + + if (bc->nt) { + chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n"); + misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); + } else { + chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n"); + misdn_lib_send_event(bc, EVENT_RELEASE); + } + } else { int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); @@ -3633,12 +3671,12 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } break; case EVENT_DISCONNECT: + /*we might not have an ch->ast ptr here anymore*/ { - struct chan_list *holded_ch=find_holded(cl_te, bc); - - send_cause2ast(ch->ast,bc); + if (ch->ast) + send_cause2ast(ch->ast,bc); chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->orginator, bc->nt, misdn_inband_avail(bc), ch->state); @@ -3655,7 +3693,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } /*Check for holded channel, to implement transfer*/ - if (holded_ch ) { + if (holded_ch && ch->ast ) { if (ch->state == MISDN_CONNECTED ) { misdn_transfer_bc(ch, holded_ch) ; misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); @@ -3722,10 +3760,18 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n"); if (!ast->generator) break; + + tmp = ast->generatordata; ast->generatordata = NULL; generate = ast->generator->generate; + + if (tone_len <0 || tone_len > 512 ) { + ast_log(LOG_WARNING, "TONE_GEN: len was %d, set to 128\n",tone_len); + tone_len=128; + } + res = generate(ast, tmp, tone_len, tone_len); ast->generatordata = tmp; @@ -3788,18 +3834,26 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } break; case EVENT_TIMEOUT: - - misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); - break; { - switch (ch->state) { + switch (ch->state) { + case MISDN_WAITING4DIGS: case MISDN_CALLING: - - chan_misdn_log(-1, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1); - break; case MISDN_DIALING: case MISDN_PROGRESS: - break; + + if (bc->nt) { + bc->progress_indicator=8; + tone_indicate(ch, TONE_BUSY); + } + + bc->out_cause=1; + misdn_lib_send_event(bc,EVENT_DISCONNECT); + break; + + case MISDN_CLEANING: + chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n"); + break; + default: misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); } @@ -3883,7 +3937,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) { ch=MISDN_ASTERISK_TECH_PVT(bridged); - //ch->state=MISDN_FACILITY_DEFLECTED; + /*ch->state=MISDN_FACILITY_DEFLECTED;*/ if (ch->bc) { /* todo */ } diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index 3544184b4..f45802200 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -61,7 +61,7 @@ void get_show_stack_details(int port, char *buf) if (stack) { sprintf(buf, "* Stack Addr:%x Port %d Type %s Prot. %s L2Link %s L1Link:%s", stack->upper_id, stack->port, stack->nt?"NT":"TE", stack->ptp?"PTP":"PMP", stack->l2link?"UP":"DOWN", stack->l1link?"UP":"DOWN"); - + } else { buf[0]=0; } @@ -329,7 +329,7 @@ int send_msg (int midev, struct misdn_bchannel *bc, msg_t *dmsg) } -static int mypid=0; +static int mypid=1; int misdn_cap_is_speech(int cap) @@ -425,6 +425,7 @@ char *bc_state2str(enum bchannel_state state) { {"BCHAN_RELEASE", BCHAN_RELEASE}, {"BCHAN_RELEASED", BCHAN_RELEASED}, {"BCHAN_CLEAN", BCHAN_CLEAN}, + {"BCHAN_CLEAN_REQUEST", BCHAN_CLEAN_REQUEST}, {"BCHAN_ERROR", BCHAN_ERROR} }; @@ -550,8 +551,13 @@ void empty_bc(struct misdn_bchannel *bc) bc->holded_bc=NULL; - bc_state_change(bc,BCHAN_EMPTY); - bc_next_state_change(bc,BCHAN_EMPTY); + + if (bc->bc_state != BCHAN_SETUP) { + bc_state_change(bc,BCHAN_EMPTY); + bc_next_state_change(bc,BCHAN_EMPTY); + } else { + cb_log(-1,bc->port,"Emptying bc(%x) within SETSTACK!\n",bc->addr); + } } @@ -581,6 +587,12 @@ int clean_up_bc(struct misdn_bchannel *bc) case BCHAN_BRIDGED: cb_log(2, stack->port, "$$$ bc still bridged\n"); + break; + + + case BCHAN_SETUP: + bc_state_change(bc,BCHAN_CLEAN_REQUEST); + return -1; default: break; } @@ -804,7 +816,7 @@ static int create_process (int midev, struct misdn_bchannel *bc) { ncr.len = 0; bc->l3_id = l3_id; - if (mypid>5000) mypid=0; + if (mypid>5000) mypid=1; bc->pid=mypid++; cb_log(3, stack->port, " --> new_l3id %x\n",l3_id); @@ -837,7 +849,7 @@ static int create_process (int midev, struct misdn_bchannel *bc) { /* send message */ bc->l3_id = l3_id; - if (mypid>5000) mypid=0; + if (mypid>5000) mypid=1; bc->pid=mypid++; cb_log(3, stack->port, "--> new_l3id %x\n",l3_id); @@ -1442,7 +1454,7 @@ int handle_new_process(struct misdn_stack *stack, iframe_t *frm) cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo); bc->l3_id=frm->dinfo; - if (mypid>5000) mypid=0; + if (mypid>5000) mypid=1; bc->pid=mypid++; return 0; } @@ -1711,11 +1723,11 @@ handle_event_nt(void *dat, void *arg) #endif break; - case CC_CONNECT|INDICATION: case CC_ALERTING|INDICATION: case CC_PROCEEDING|INDICATION: case CC_SETUP_ACKNOWLEDGE|INDICATION: - + if(!stack->ptp) break; + case CC_CONNECT|INDICATION: { struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); @@ -2104,16 +2116,19 @@ int handle_bchan(msg_t *msg) cb_log(4, stack->port," --> Got Adr %x\n", bc->addr); free_msg(msg); + - if (bc->bc_state != BCHAN_SETUP) { - cb_log(4, stack->port," --> STATE WASN'T SETUP in SETSTACK|IND\n"); + switch(bc->bc_state) { + case BCHAN_SETUP: + bc_state_change(bc,BCHAN_SETUPED); + manager_bchannel_activate(bc); + break; + + case BCHAN_CLEAN_REQUEST: + default: + cb_log(-1, stack->port," --> STATE WASN'T SETUP (but %s) in SETSTACK|IND\n",bc_state2str(bc->bc_state)); + clean_up_bc(bc); } - - bc_state_change(bc,BCHAN_SETUPED); - - - manager_bchannel_activate(bc); - return 1; case MGR_DELLAYER| INDICATION: @@ -2885,7 +2900,7 @@ void misdn_lib_log_ies(struct misdn_bchannel *bc) cb_log(3, stack->port, " --> screen:%d --> pres:%d\n", bc->screen, bc->pres); - 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(2, stack->port, " --> channel:%d caps:%s pi:%x keypad:%s sending_complete:%d\n", bc->channel, bearer2str(bc->capability),bc->progress_indicator, bc->keypad, bc->sending_complete); cb_log(3, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1); @@ -2933,11 +2948,13 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) } break; - case EVENT_CONNECT: case EVENT_PROGRESS: case EVENT_ALERTING: case EVENT_PROCEEDING: case EVENT_SETUP_ACKNOWLEDGE: + if (!bc->nt && !stack->ptp) break; + + case EVENT_CONNECT: case EVENT_RETRIEVE_ACKNOWLEDGE: if (stack->nt) { if (bc->channel <=0 ) { /* else we have the channel already */ diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h index 34309a584..b8af625aa 100644 --- a/channels/misdn/isdn_lib.h +++ b/channels/misdn/isdn_lib.h @@ -35,6 +35,7 @@ enum bchannel_state { BCHAN_RELEASE, BCHAN_RELEASED, BCHAN_CLEAN, + BCHAN_CLEAN_REQUEST, BCHAN_ERROR }; |