diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index c2bf772f02..8bebe2a1d3 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -668,6 +668,7 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel " --> bc_l3id: %x\n" " --> display: %s\n" " --> activated: %d\n" + " --> state: %s\n" " --> capability: %s\n" " --> echo_cancel: %d\n" " --> notone : rx %d tx:%d\n" @@ -680,6 +681,7 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel bc->display, bc->active, + bc_state2str(bc->bc_state), bearer2str(bc->capability), bc->ec_enable, help->norxtone,help->notxtone, @@ -2032,6 +2034,14 @@ 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"); + + tmp->frame.frametype = AST_FRAME_NULL; + tmp->frame.subclass = 0; + return &tmp->frame; + } + /*shrinken len if necessary, we transmit at maximum 4k*/ len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf); @@ -2080,7 +2090,7 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame) if ( !frame->subclass) { - chan_misdn_log(2, ch->bc->port, "misdn_write: * prods us\n"); + chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n"); return 0; } @@ -2090,6 +2100,16 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame) return -1; } + + if ( !frame->samples ) { + chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n"); + return 0; + } + + if ( ! ch->bc->addr ) { + chan_misdn_log(4, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples); + return 0; + } #if MISDN_DEBUG { @@ -2102,9 +2122,13 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame) } #endif - - if (!ch->bc->active) { - chan_misdn_log(5, ch->bc->port, "BC not active droping: %d frames\n",frame->samples); + + switch (ch->bc->bc_state) { + case BCHAN_ACTIVATED: + case BCHAN_BRIDGED: + break; + default: + chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x\n",frame->samples,ch->bc->addr); return 0; } @@ -2166,13 +2190,13 @@ enum ast_bridge_result misdn_bridge (struct ast_channel *c0, if ( !ecwb ) { chan_misdn_log(2, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n"); ch1->bc->ec_enable=0; - manager_ec_disable(ch1->bc); + /* manager_ec_disable(ch1->bc); */ } misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int)); if ( !ecwb ) { chan_misdn_log(2, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n"); ch2->bc->ec_enable=0; - manager_ec_disable(ch2->bc); + /* manager_ec_disable(ch2->bc); */ } /* trying to make a mISDN_dsp conference */ @@ -2707,7 +2731,7 @@ static struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long if (help->l3id == l3id ) return help; } - chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id); + chan_misdn_log(6, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id); return NULL; } @@ -2719,7 +2743,7 @@ static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bc if (help->bc == bc) return help; } - chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad); + chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad); return NULL; } @@ -2729,14 +2753,14 @@ static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchann { struct chan_list *help=list; - chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad); + chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad); for (;help; help=help->next) { chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel); if (help->bc->port == bc->port && help->bc->holded ) return help; } - chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad); + chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad); return NULL; } @@ -3068,6 +3092,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */ chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad); misdn_lib_log_ies(bc); + chan_misdn_log(2,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state)); } if (event != EVENT_SETUP) { @@ -3468,8 +3493,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE); case EVENT_CONNECT_ACKNOWLEDGE: { - bc->state=STATE_CONNECTED; - ch->l3id=bc->l3_id; ch->addr=bc->addr; @@ -3592,8 +3615,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } else { int len=bc->bframe_len; int free=misdn_ibuf_freecount(bc->astbuf); - - + if (bc->bframe_len > free) { ast_log(LOG_DEBUG, "sbuf overflow!\n"); len=misdn_ibuf_freecount(bc->astbuf); @@ -3693,13 +3715,17 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } } #endif + struct ast_channel *bridged=AST_BRIDGED_P(ch->ast); - if (AST_BRIDGED_P(ch->ast)){ + if (bridged){ + struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged); ch->state = MISDN_HOLDED; ch->l3id = bc->l3_id; - ast_moh_start(AST_BRIDGED_P(ch->ast), NULL); + bc->holded_bc=bridged_ch->bc; misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE); + + ast_moh_start(bridged, NULL); } else { misdn_lib_send_event(bc, EVENT_HOLD_REJECT); chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n"); @@ -3729,10 +3755,14 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) break; default: - chan_misdn_log(1,bc->port," --> not yet handled\n"); + chan_misdn_log(1, bc->port," --> not yet handled\n"); } break; + + + case EVENT_RESTART: + break; default: ast_log(LOG_WARNING, "Got Unknown Event\n"); diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index 8053168054..f9d5029ff6 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -14,6 +14,11 @@ #include "isdn_lib_intern.h" #include + +void misdn_join_conf(struct misdn_bchannel *bc, int conf_id); +void misdn_split_conf(struct misdn_bchannel *bc, int conf_id); + + void misdn_free_ibuffer(void *ibuf) { free_ibuffer((ibuffer_t*)ibuf); @@ -389,7 +394,7 @@ void dump_chan_list(struct misdn_stack *stack) int i; for (i=0; i b_num; i++) { - cb_log(5, stack->port, "Idx:%d stack->cchan:%d Chan:%d\n",i,stack->channels[i], i+1); + cb_log(8, stack->port, "Idx:%d stack->cchan:%d Chan:%d\n",i,stack->channels[i], i+1); } } @@ -431,16 +436,72 @@ int empty_chan_in_stack(struct misdn_stack *stack, int channel) return 0; } +char *bc_state2str(enum bchannel_state state) { + int i; + + struct bchan_state_s { + char *n; + enum bchannel_state s; + } states[] = { + {"BCHAN_CLEANED", BCHAN_CLEANED }, + {"BCHAN_EMPTY", BCHAN_EMPTY}, + {"BCHAN_SETUP", BCHAN_SETUP}, + {"BCHAN_SETUPED", BCHAN_SETUPED}, + {"BCHAN_ACTIVE", BCHAN_ACTIVE}, + {"BCHAN_ACTIVATED", BCHAN_ACTIVATED}, + {"BCHAN_BRIDGE", BCHAN_BRIDGE}, + {"BCHAN_BRIDGED", BCHAN_BRIDGED}, + {"BCHAN_RELEASE", BCHAN_RELEASE}, + {"BCHAN_RELEASED", BCHAN_RELEASED}, + {"BCHAN_CLEAN", BCHAN_CLEAN}, + {"BCHAN_ERROR", BCHAN_ERROR} + }; + + for (i=0; i< sizeof(states)/sizeof(struct bchan_state_s); i++) + if ( states[i].s == state) + return states[i].n; + + return "UNKNOWN"; +} + +void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state) +{ + cb_log(3,bc->port,"BC_STATE_CHANGE: from:%s to:%s\n", + bc_state2str(bc->bc_state), + bc_state2str(state) ); + + switch (state) { + case BCHAN_ACTIVATED: + if (bc->next_bc_state == BCHAN_BRIDGED) { + misdn_join_conf(bc, bc->conf_id); + bc->next_bc_state = BCHAN_EMPTY; + return; + } + default: + bc->bc_state=state; + break; + } +} + +void bc_next_state_change(struct misdn_bchannel *bc, enum bchannel_state state) +{ + cb_log(3,bc->port,"BC_NEXT_STATE_CHANGE: from:%s to:%s\n", + bc_state2str(bc->next_bc_state), + bc_state2str(state) ); + + bc->next_bc_state=state; +} + void empty_bc(struct misdn_bchannel *bc) { bc->bframe_len=0; - - bc->state=STATE_NOTHING; bc->channel = 0; bc->in_use = 0; + bc->conf_id = 0; + bc->need_more_infos = 0; bc->send_dtmf=0; @@ -510,6 +571,11 @@ void empty_bc(struct misdn_bchannel *bc) bc->fac_type=FACILITY_NONE; bc->te_choose_channel = 0; + + bc->holded_bc=NULL; + + bc_state_change(bc,BCHAN_EMPTY); + bc_next_state_change(bc,BCHAN_EMPTY); } @@ -518,43 +584,44 @@ int clean_up_bc(struct misdn_bchannel *bc) int ret=0; unsigned char buff[32]; struct misdn_stack * stack; + + cb_log(2, 0, "$$$ CLEANUP CALLED\n"); if (!bc ) return -1; stack=get_stack_by_bc(bc); + if (!stack) return -1; - if (!bc->upset) { + switch (bc->bc_state ) { + + case BCHAN_CLEANED: cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid); return -1; - } - - if (bc->active) { + + case BCHAN_ACTIVATED: cb_log(2, stack->port, "$$$ bc still active, deactivatiing .. stid :%x\n", bc->b_stid); manager_bchannel_deactivate(bc); + break; + + case BCHAN_BRIDGED: + cb_log(2, stack->port, "$$$ bc still bridged\n"); + default: + break; } cb_log(5, stack->port, "$$$ Cleaning up bc with stid :%x\n", bc->b_stid); - if ( misdn_cap_is_speech(bc->capability) && bc->ec_enable) { manager_ec_disable(bc); } + cb_log(2, stack->port, "$$$ CLEARING STACK\n"); + /*mISDN_clear_stack(stack->midev,bc->b_stid);*/ + mISDN_write_frame(stack->midev, buff, bc->addr|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); - -#ifdef ACK_HDLC - if (bc->ack_hdlc ) { - free(bc->ack_hdlc); - bc->ack_hdlc=NULL; - } -#endif - - bc->b_stid = 0; - - bc->upset=0; - + bc_state_change(bc, BCHAN_CLEANED); return ret; } @@ -818,14 +885,9 @@ int setup_bc(struct misdn_bchannel *bc) int channel=bc->channel-1-(bc->channel>16); int b_stid=stack->b_stids[channel>=0?channel:0]; -#if 0 - if (bc->hdlc) { - clean_up_bc(bc); - } -#endif - - if (bc->upset) { - cb_log(4, stack->port, "$$$ bc already upsetted stid :%x\n", b_stid); + + if ( bc->bc_state != BCHAN_CLEANED) { + cb_log(4, stack->port, "$$$ bc already upsetted stid :%x (state:%s)\n", b_stid, bc_state2str(bc->bc_state) ); return -1; } @@ -833,7 +895,8 @@ int setup_bc(struct misdn_bchannel *bc) if (b_stid <= 0) { cb_log(-1, stack->port," -- Stid <=0 at the moment in channel:%d\n",channel); - + + bc_state_change(bc,BCHAN_ERROR); return 1; } @@ -882,7 +945,8 @@ int setup_bc(struct misdn_bchannel *bc) ret = mISDN_new_layer(midev, &li); if (ret ) { cb_log(-1, stack->port,"New Layer Err: %d %s\n",ret,strerror(errno)); - + + bc_state_change(bc,BCHAN_ERROR); return(-EINVAL); } @@ -930,25 +994,18 @@ int setup_bc(struct misdn_bchannel *bc) cb_log(5, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno)); mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + + bc_state_change(bc,BCHAN_ERROR); return(-EINVAL); } -#if 0 - ret = mISDN_get_setstack_ind(midev, bc->layer_id ); - - if (ret){ - cb_log(5, stack->port,"$$$ Get Set Stack Err: %d %s\n",ret,strerror(errno)); - - mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); - return(-EINVAL); - } -#endif + bc_state_change(bc,BCHAN_SETUP); - bc->upset=1; + /*manager_bchannel_deactivate(bc);*/ + - manager_bchannel_deactivate(bc); return 0; } @@ -975,7 +1032,8 @@ int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, in empty_bc(bc); - bc->upset=0; + bc_state_change(bc, BCHAN_CLEANED); + bc->port=stack->port; bc->nt=stack->nt?1:0; @@ -1378,7 +1436,7 @@ int handle_new_process(struct misdn_stack *stack, iframe_t *frm) return -1; } - cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo); + cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo); bc->l3_id=frm->dinfo; if (mypid>5000) mypid=0; @@ -1392,7 +1450,7 @@ int handle_cr ( struct misdn_stack *stack, iframe_t *frm) switch (frm->prim) { case CC_NEW_CR|INDICATION: - cb_log(4, stack->port, " --> lib: NEW_CR Ind with l3id:%x on this port.\n",frm->dinfo); + cb_log(7, stack->port, " --> lib: NEW_CR Ind with l3id:%x on this port.\n",frm->dinfo); handle_new_process(stack, frm); return 1; case CC_NEW_CR|CONFIRM: @@ -1721,16 +1779,8 @@ handle_event_nt(void *dat, void *arg) break; case CC_RELEASE|CONFIRM: - { - /*struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); - cb_log(3, stack->port, " --> RELEASE CONFIRM, doing nothin\n"); - cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data); - empty_chan_in_stack(stack,bc->channel); - empty_bc(bc); - free_msg(msg); - return 0;*/ - } - break; + break; + case CC_RELEASE|INDICATION: break; @@ -1991,10 +2041,14 @@ int handle_bchan(msg_t *msg) } switch (frm->prim) { + + case MGR_SETSTACK| CONFIRM: + cb_log(2, stack->port, "BCHAN: MGR_SETSTACK|CONFIRM \n"); + break; + case MGR_SETSTACK| INDICATION: cb_log(2, stack->port, "BCHAN: MGR_SETSTACK|IND \n"); - 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)); @@ -2005,28 +2059,46 @@ int handle_bchan(msg_t *msg) } cb_log(4, stack->port," --> Got Adr %x\n", bc->addr); - - bc->upset=2; - + free_msg(msg); + if (bc->bc_state != BCHAN_SETUP) { + cb_log(4, stack->port," --> STATE WASN'T SETUP in SETSTACK|IND\n"); + } + + bc_state_change(bc,BCHAN_SETUPED); + + manager_bchannel_activate(bc); return 1; + + case MGR_DELLAYER| INDICATION: + cb_log(2, stack->port, "BCHAN: MGR_DELLAYER|IND\n"); + break; + case MGR_DELLAYER| CONFIRM: cb_log(2, stack->port, "BCHAN: MGR_DELLAYER|CNF \n"); + bc_state_change(bc,BCHAN_CLEANED); + free_msg(msg); return 1; case PH_ACTIVATE | INDICATION: case DL_ESTABLISH | INDICATION: cb_log(4, stack->port, "BCHAN: ACT Ind\n"); + + bc_state_change(bc,BCHAN_ACTIVATED); + free_msg(msg); return 1; case PH_ACTIVATE | CONFIRM: case DL_ESTABLISH | CONFIRM: + + bc_state_change(bc,BCHAN_ACTIVATED); + cb_log(4, stack->port, "BCHAN: bchan ACT Confirm\n"); free_msg(msg); @@ -2035,12 +2107,16 @@ int handle_bchan(msg_t *msg) case PH_DEACTIVATE | INDICATION: case DL_RELEASE | INDICATION: cb_log (4, stack->port, "BCHAN: DeACT Ind\n"); + + bc_state_change(bc,BCHAN_RELEASED); free_msg(msg); return 1; case PH_DEACTIVATE | CONFIRM: case DL_RELEASE | CONFIRM: cb_log(4, stack->port, "BCHAN: DeACT Conf\n"); + + bc_state_change(bc,BCHAN_RELEASED); free_msg(msg); return 1; @@ -2089,14 +2165,26 @@ int handle_bchan(msg_t *msg) /** Anyway flip the bufbits **/ if ( misdn_cap_is_speech(bc->capability) ) flip_buf_bits(bc->bframe, bc->bframe_len); - + + + if (!bc->bframe_len) { + cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr); + free_msg(msg); + return 1; + } + + if ( (bc->addr&STACK_ID_MASK) != (frm->addr&STACK_ID_MASK) ) { + cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr); + free_msg(msg); + return 1; + } #if MISDN_DEBUG cb_log(-1, stack->port, "DL_DATA INDICATION Len %d\n", frm->len); #endif - if (bc->active && frm->len > 0) { + if ( (bc->bc_state == BCHAN_ACTIVATED) && frm->len > 0) { if ( !do_tone(bc, frm->len) ) { if ( misdn_cap_is_speech(bc->capability)) { @@ -2107,7 +2195,7 @@ int handle_bchan(msg_t *msg) int i=cb_event( EVENT_BCHAN_DATA, bc, glob_mgr->user_data); if (i<0) { - cb_log(5,stack->port,"cb_event returned <0\n"); + cb_log(10,stack->port,"cb_event returned <0\n"); /*clean_up_bc(bc);*/ } } @@ -2116,6 +2204,12 @@ int handle_bchan(msg_t *msg) return 1; } + + case PH_CONTROL | CONFIRM: + cb_log(2, stack->port, "PH_CONTROL|CNF bc->addr:%x\n", frm->addr); + free_msg(msg); + return 1; + case PH_DATA | CONFIRM: case DL_DATA|CONFIRM: #if MISDN_DEBUG @@ -2124,13 +2218,7 @@ int handle_bchan(msg_t *msg) #endif free_msg(msg); - -#ifdef ACK_HDLC - if (bc->hdlc) { - cb_log(4,stack->port,"Acknowledge Packet\n"); - sem_post( (sem_t*)bc->ack_hdlc); - } -#endif + return 1; case DL_DATA|RESPONSE: #if MISDN_DEBUG @@ -2385,6 +2473,13 @@ int handle_mgmt(msg_t *msg) struct misdn_stack * stack=find_stack_by_addr(frm->addr); if (!stack) { + if (frm->prim == (MGR_DELLAYER|CONFIRM)) { + cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: %x !\n", + frm->addr) ; + free(msg); + return 1; + } + return 0; } @@ -2707,6 +2802,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) } cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad); + cb_log(1, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state)); misdn_lib_log_ies(bc); switch (event) { @@ -2782,14 +2878,22 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) stack_holder_add(stack,holded_bc); if (stack->nt) { + if (bc->bc_state == BCHAN_BRIDGED) { + misdn_split_conf(bc,bc->conf_id); + misdn_split_conf(bc->holded_bc,bc->holded_bc->conf_id); + /*bc_state_change(bc,BCHAN_SETUPED); + manager_bchannel_activate(bc);*/ + } + 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; + /*holded_bc->upset=0; + holded_bc->active=0;*/ + bc_state_change(holded_bc,BCHAN_CLEANED); cb_event( EVENT_NEW_BC, holded_bc, glob_mgr->user_data); } @@ -2866,7 +2970,7 @@ int manager_isdn_handler(iframe_t *frm ,msg_t *msg) if (handle_frm(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); @@ -3227,20 +3331,27 @@ void manager_bchannel_activate(struct misdn_bchannel *bc) return ; } - if (bc->upset != 2 ) { - cb_log(1, stack->port, "bchannel_activate: BC Not properly upsetted addr:%x\n", bc->addr); + + switch (bc->bc_state) { + + case BCHAN_SETUPED: + break; + + default: + cb_log(1, stack->port, "bchannel_activate: BC Not properly upsetted (state:%s) addr:%x\n", bc_state2str(bc->bc_state), bc->addr); + + return; } + frm=(iframe_t*)msg->data; /* we must activate if we are deactivated */ clear_ibuffer(bc->astbuf); - if (bc->active) return; - cb_log(5, stack->port, "$$$ Bchan Activated addr %x\n", bc->addr); - + /* activate bchannel */ frm->prim = DL_ESTABLISH | REQUEST; frm->addr = bc->addr | FLG_MSG_DOWN ; @@ -3249,9 +3360,9 @@ void manager_bchannel_activate(struct misdn_bchannel *bc) msg_queue_tail(&glob_mgr->activatequeue, msg); sem_post(&glob_mgr->new_msg); - - bc->active=1; - + + bc_state_change(bc, BCHAN_ACTIVE); + return ; } @@ -3262,20 +3373,33 @@ void manager_bchannel_deactivate(struct misdn_bchannel * bc) iframe_t dact; struct misdn_stack *stack=get_stack_by_bc(bc); - if (!bc->active) return; - + + + switch (bc->bc_state) { + case BCHAN_ACTIVATED: + break; + case BCHAN_BRIDGED: + misdn_split_conf(bc,bc->conf_id); + break; + default: + cb_log( 4, bc->port,"bchan_deactivate: called but not activated\n"); + return ; + + } + cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr); - + bc->generate_tone=0; dact.prim = DL_RELEASE | REQUEST; dact.addr = bc->addr | FLG_MSG_DOWN; dact.dinfo = 0; dact.len = 0; - + mISDN_write(stack->midev, &dact, mISDN_HEADER_LEN+dact.len, TIMEOUT_1SEC); clear_ibuffer(bc->astbuf); - bc->active=0; + + bc_state_change(bc,BCHAN_RELEASE); return; } @@ -3284,7 +3408,15 @@ void manager_bchannel_deactivate(struct misdn_bchannel * bc) int misdn_lib_tx2misdn_frm(struct misdn_bchannel *bc, void *data, int len) { struct misdn_stack *stack=get_stack_by_bc(bc); - if (!bc->active) return -1; + + switch (bc->bc_state) { + case BCHAN_ACTIVATED: + case BCHAN_BRIDGED: + break; + default: + cb_log(3, bc->port, "BC not yet activated (state:%s)\n",bc_state2str(bc->bc_state)); + return -1; + } char buf[4096 + mISDN_HEADER_LEN]; iframe_t *frm= (iframe_t*)buf; @@ -3359,9 +3491,6 @@ void manager_clean_bc(struct misdn_bchannel *bc ) { struct misdn_stack *stack=get_stack_by_bc(bc); - if (bc->state == STATE_CONNECTED) - misdn_lib_send_event(bc,EVENT_DISCONNECT); - empty_chan_in_stack(stack, bc->channel); empty_bc(bc); @@ -3491,21 +3620,72 @@ struct misdn_stack* get_misdn_stack() { -void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2) { - manager_ph_control(bc1, CMX_RECEIVE_OFF, 0); - manager_ph_control(bc2, CMX_RECEIVE_OFF, 0); +void misdn_join_conf(struct misdn_bchannel *bc, int conf_id) +{ + bc_state_change(bc,BCHAN_BRIDGED); + manager_ph_control(bc, CMX_RECEIVE_OFF, 0); + manager_ph_control(bc, CMX_CONF_JOIN, conf_id); + + cb_log(1,bc->port, "Joining bc:%x in conf:%d\n",bc->addr,conf_id); + + char data[16]; + int len=15; + + memset(data,0,15); - manager_ph_control(bc1, CMX_CONF_JOIN, (bc1->pid<<1) +1); - manager_ph_control(bc2, CMX_CONF_JOIN, (bc1->pid<<1) +1); + misdn_lib_tx2misdn_frm(bc, data, len); + +} + + +void misdn_split_conf(struct misdn_bchannel *bc, int conf_id) +{ + bc_state_change(bc,BCHAN_ACTIVATED); + manager_ph_control(bc, CMX_RECEIVE_ON, 0); + manager_ph_control(bc, CMX_CONF_SPLIT, conf_id); + + cb_log(1,bc->port, "Splitting bc:%x in conf:%d\n",bc->addr,conf_id); +} + +void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2) { + int conf_id=(bc1->pid<<1) +1; + + cb_log(1, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port); + + struct misdn_bchannel *bc_list[]={ + bc1,bc2,NULL + }; + struct misdn_bchannel **bc; + + for (bc=bc_list; *bc; *bc++) { + (*bc)->conf_id=conf_id; + cb_log(1, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr); + + switch((*bc)->bc_state) { + case BCHAN_ACTIVATED: + misdn_join_conf(*bc,conf_id); + break; + default: + bc_next_state_change(*bc,BCHAN_BRIDGED); + break; + } + } } void misdn_lib_split_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2) { - - manager_ph_control(bc1, CMX_RECEIVE_ON, 0) ; - manager_ph_control(bc2, CMX_RECEIVE_ON, 0); - - manager_ph_control(bc1, CMX_CONF_SPLIT, (bc1->pid<<1) +1); - manager_ph_control(bc2, CMX_CONF_SPLIT, (bc1->pid<<1) +1); + + struct misdn_bchannel *bc_list[]={ + bc1,bc2,NULL + }; + struct misdn_bchannel **bc; + + for (bc=bc_list; *bc; *bc++) { + if ( (*bc)->bc_state == BCHAN_BRIDGED){ + misdn_split_conf( *bc, (*bc)->conf_id); + } else { + cb_log( 2, (*bc)->port, "BC not bridged (state:%s) so not splitting it\n",bc_state2str((*bc)->bc_state)); + } + } } diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h index 2c99d946ba..1e94c7896b 100644 --- a/channels/misdn/isdn_lib.h +++ b/channels/misdn/isdn_lib.h @@ -23,20 +23,27 @@ #define MAX_BCHANS 30 -enum bc_state_e { - STATE_NOTHING=0, - STATE_NULL, - STATE_CALL_INIT, - STATE_CONNECTED, - STATE_HOLD_ACKNOWLEDGE +enum bchannel_state { + BCHAN_CLEANED=0, + BCHAN_EMPTY, + BCHAN_SETUP, + BCHAN_SETUPED, + BCHAN_ACTIVE, + BCHAN_ACTIVATED, + BCHAN_BRIDGE, + BCHAN_BRIDGED, + BCHAN_RELEASE, + BCHAN_RELEASED, + BCHAN_CLEAN, + BCHAN_ERROR }; + enum misdn_err_e { ENOCHAN=1 }; - enum mISDN_NUMBER_PLAN { NUMPLAN_UNINITIALIZED=-1, NUMPLAN_INTERNATIONAL=0x1, @@ -54,7 +61,6 @@ enum event_response_e { }; - enum event_e { EVENT_NOTHING, EVENT_TONE_GENERATE, @@ -243,11 +249,16 @@ struct misdn_bchannel { int generate_tone; int tone_cnt; - - enum bc_state_e state; + + enum bchannel_state bc_state; + enum bchannel_state next_bc_state; + int conf_id; + int holded; int stack_holder; + + struct misdn_bchannel *holded_bc; int pres; int screen; @@ -390,4 +401,11 @@ int misdn_lib_is_ptp(int port); #define PRI_TRANS_CAP_3_1K_AUDIO 0x10 #define PRI_TRANS_CAP_7K_AUDIO 0x11 + + +char *bc_state2str(enum bchannel_state state); +void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state); + + + #endif