diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 6e97289797a36eb425e7c5d3a9773c0c1e12a9b4..aa1207ceb5aa681380b0100b39410e4618228a56 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -151,6 +151,8 @@ struct chan_list { ast_mutex_t lock; + char allowed_bearers[BUFFERSIZE+1]; + enum misdn_chan_state state; int holded; int orginator; @@ -346,12 +348,28 @@ static struct chan_list * get_chan_by_ast_name(char *name) } + +struct allowed_bearers { + int cap; + int val; + char *name; +}; + +struct allowed_bearers allowed_bearers_array[]={ + {INFO_CAPABILITY_SPEECH,1,"speech"}, + {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"}, + {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"}, + {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"}, + {INFO_CAPABILITY_VIDEO,16,"video"} +}; + static char *bearer2str(int cap) { static char *bearers[]={ "Speech", "Audio 3.1k", "Unres Digital", "Res Digital", + "Video", "Unknown Bearer" }; @@ -368,9 +386,12 @@ static char *bearer2str(int cap) { case INFO_CAPABILITY_DIGITAL_RESTRICTED: return bearers[3]; break; - default: + case INFO_CAPABILITY_VIDEO: return bearers[4]; break; + default: + return bearers[5]; + break; } } @@ -1153,7 +1174,7 @@ static int update_config (struct chan_list *ch, int orig) int port=bc->port; - chan_misdn_log(1,port,"update_config: Getting Config\n"); + chan_misdn_log(5,port,"update_config: Getting Config\n"); int hdlc=0; @@ -1243,7 +1264,7 @@ static void config_jitterbuffer(struct chan_list *ch) struct misdn_bchannel *bc=ch->bc; int len=ch->jb_len, threshold=ch->jb_upper_threshold; - chan_misdn_log(1,bc->port, "config_jb: Called\n"); + chan_misdn_log(5,bc->port, "config_jb: Called\n"); if ( ! len ) { chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n"); @@ -1295,6 +1316,10 @@ void debug_numplan(int port, int numplan, char *type) } } + + + + static int read_config(struct chan_list *ch, int orig) { if (!ch) { @@ -1335,6 +1360,9 @@ static int read_config(struct chan_list *ch, int orig) { misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int)); misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int)); + + misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE); + int hdlc=0; misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int)); @@ -1394,7 +1422,7 @@ static int read_config(struct chan_list *ch, int orig) { misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg)); misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg)); - chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg)); + chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg)); ast->pickupgroup=pg; ast->callgroup=cg; } @@ -2228,18 +2256,20 @@ static enum ast_bridge_result misdn_bridge (struct ast_channel *c0, int bridging; misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int)); if (bridging) { - int ecwb; + int ecwb, ec; misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int)); - if ( !ecwb ) { + misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int)); + if ( !ecwb && ec ) { 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 ) { + misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int)); + if ( !ecwb && ec) { 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 */ @@ -2291,7 +2321,7 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone) const struct tone_zone_sound *ts= NULL; struct ast_channel *ast=cl->ast; - chan_misdn_log(2,cl->bc->port,"Tone Indicate:\n"); + chan_misdn_log(3,cl->bc->port,"Tone Indicate:\n"); if (!cl->ast) { return 0; @@ -2299,24 +2329,24 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone) switch (tone) { case TONE_DIAL: - chan_misdn_log(2,cl->bc->port," --> Dial\n"); + chan_misdn_log(3,cl->bc->port," --> Dial\n"); ts=ast_get_indication_tone(ast->zone,"dial"); misdn_lib_tone_generator_start(cl->bc); break; case TONE_ALERTING: - chan_misdn_log(2,cl->bc->port," --> Ring\n"); + chan_misdn_log(3,cl->bc->port," --> Ring\n"); ts=ast_get_indication_tone(ast->zone,"ring"); misdn_lib_tone_generator_stop(cl->bc); break; case TONE_FAR_ALERTING: /* VERY UGLY HACK, BECAUSE CHAN_SIP DOES NOT GENERATE TONES */ - chan_misdn_log(2,cl->bc->port," --> Ring\n"); + chan_misdn_log(3,cl->bc->port," --> Ring\n"); ts=ast_get_indication_tone(ast->zone,"ring"); misdn_lib_tone_generator_start(cl->bc); misdn_lib_echo(cl->bc,1); break; case TONE_BUSY: - chan_misdn_log(2,cl->bc->port," --> Busy\n"); + chan_misdn_log(3,cl->bc->port," --> Busy\n"); ts=ast_get_indication_tone(ast->zone,"busy"); misdn_lib_tone_generator_stop(cl->bc); break; @@ -2324,7 +2354,7 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone) break; case TONE_NONE: - chan_misdn_log(2,cl->bc->port," --> None\n"); + chan_misdn_log(3,cl->bc->port," --> None\n"); misdn_lib_tone_generator_stop(cl->bc); ast_playtones_stop(ast); break; @@ -2784,8 +2814,8 @@ static void release_chan(struct misdn_bchannel *bc) { } release_unlock; - chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id); - + chan_misdn_log(1, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id); + //releaseing jitterbuffer if (ch->jb ) { misdn_jb_destroy(ch->jb); @@ -3325,6 +3355,24 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) /** queue new chan **/ cl_queue_chan(&cl_te, ch) ; + + + if (!strstr(ch->allowed_bearers,"all")) { + int i; + for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) { + if (allowed_bearers_array[i].cap == bc->capability) { + if ( !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) { + chan_misdn_log(0,bc->port,"Bearer Not allowed\b"); + bc->out_cause=88; + + ch->state=MISDN_EXTCANTMATCH; + misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); + return RESPONSE_OK; + } + } + + } + } /* Check for Pickup Request first */ if (!strcmp(chan->exten, ast_pickup_ext())) { @@ -3380,7 +3428,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) if (bc->nt) misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); else - misdn_lib_send_event(bc, EVENT_DISCONNECT ); + misdn_lib_send_event(bc, EVENT_RELEASE ); + break; } @@ -3404,26 +3453,34 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) if (bc->nt) misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); else - misdn_lib_send_event(bc, EVENT_DISCONNECT ); + misdn_lib_send_event(bc, EVENT_RELEASE); } } else { - int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); - if (ret == -ENOCHAN) { - ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n"); - misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); - } - /* send tone to phone :) */ - /** ADD IGNOREPAT **/ - - int stop_tone; - misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int)); - if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) - tone_indicate(ch,TONE_NONE); - else - tone_indicate(ch,TONE_DIAL); - - ch->state=MISDN_WAITING4DIGS; + + if (bc->sending_complete) { + bc->out_cause=1; + misdn_lib_send_event(bc, EVENT_RELEASE); + } else { + + int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); + if (ret == -ENOCHAN) { + ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n"); + misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); + } + /* send tone to phone :) */ + + /** ADD IGNOREPAT **/ + + int stop_tone; + misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int)); + if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) + tone_indicate(ch,TONE_NONE); + else + tone_indicate(ch,TONE_DIAL); + + ch->state=MISDN_WAITING4DIGS; + } } } @@ -3791,8 +3848,11 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) break; - case EVENT_RESTART: + + stop_bc_tones(ch); + release_chan(bc); + break; default: diff --git a/channels/misdn/chan_misdn_config.h b/channels/misdn/chan_misdn_config.h index b119ffc65e71c76ad0bc372c8afb476be1124699..0be6d6a2ee057473370fd00d50ca48f03d4572e3 100644 --- a/channels/misdn/chan_misdn_config.h +++ b/channels/misdn/chan_misdn_config.h @@ -23,6 +23,7 @@ enum misdn_cfg_elements { /* port config items */ MISDN_CFG_FIRST = 0, MISDN_CFG_GROUPNAME, /* char[] */ + MISDN_CFG_ALLOWED_BEARERS, /* char[] */ MISDN_CFG_FAR_ALERTING, /* int (bool) */ MISDN_CFG_RXGAIN, /* int */ MISDN_CFG_TXGAIN, /* int */ diff --git a/channels/misdn/ie.c b/channels/misdn/ie.c index 6f29cb2f8b036b89382cc285e5acb7b931479614..eeeff040bcee51d262926e5108bdf027bd36ac7c 100644 --- a/channels/misdn/ie.c +++ b/channels/misdn/ie.c @@ -162,23 +162,28 @@ void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capabili *stopbits = -1; *dbits = -1; *parity = -1; - + if (!nt) { p = NULL; - if (qi->QI_ELEMENT(llc)) +#ifdef LLC_SUPPORT + if (qi->QI_ELEMENT(llc)) { + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1; - else if (qi->QI_ELEMENT(bearer_capability)) + } +#endif + if (qi->QI_ELEMENT(bearer_capability)) p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1; } if (!p) return; + if (p[0] < 2) { printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]); return; } - + *coding = (p[1]&0x60) >> 5; *capability = p[1] & 0x1f; octet = 2; diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index a969d11d90a3326b8cccadfd56eebd1281e53d7b..ad3c43ba4d43efac0de327254e019abc9961ab69 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -471,6 +471,10 @@ void empty_bc(struct misdn_bchannel *bc) bc->channel = 0; bc->in_use = 0; + bc->sending_complete = 0; + + bc->restart_channel=0; + bc->conf_id = 0; bc->need_more_infos = 0; @@ -557,7 +561,7 @@ int clean_up_bc(struct misdn_bchannel *bc) unsigned char buff[32]; struct misdn_stack * stack; - cb_log(2, 0, "$$$ CLEANUP CALLED\n"); + cb_log(3, 0, "$$$ CLEANUP CALLED\n"); if (!bc ) return -1; stack=get_stack_by_bc(bc); @@ -587,15 +591,18 @@ int clean_up_bc(struct misdn_bchannel *bc) manager_ec_disable(bc); } - mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + if (bc->bc_state == BCHAN_SETUP) + mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + else + mISDN_write_frame(stack->midev, buff, bc->addr|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); - cb_log(2, stack->port, "$$$ CLEARING STACK\n"); + cb_log(3, stack->port, "$$$ CLEARING STACK\n"); + ret=mISDN_clear_stack(stack->midev,bc->b_stid); if (ret<0) { cb_log(-1,stack->port,"clear stack failed [%s]\n",strerror(errno)); } - bc->b_stid = 0; bc_state_change(bc, BCHAN_CLEANED); @@ -612,8 +619,7 @@ void clear_l3(struct misdn_stack *stack) cb_event(EVENT_CLEANUP, &stack->bc[i], glob_mgr->user_data); empty_chan_in_stack(stack,i+1); empty_bc(&stack->bc[i]); - queue_cleanup_bc(&stack->bc[i]); - + clean_up_bc(&stack->bc[i]); } } @@ -971,19 +977,18 @@ int setup_bc(struct misdn_bchannel *bc) pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4)); } - + ret = mISDN_set_stack(midev, bc->b_stid, &pid); - + if (ret){ - cb_log(5, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno)); + cb_log(-1, 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); } - bc_state_change(bc,BCHAN_SETUP); @@ -1479,7 +1484,7 @@ int handle_cr ( struct misdn_stack *stack, iframe_t *frm) cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo); empty_chan_in_stack(stack,bc->channel); empty_bc(bc); - queue_cleanup_bc(bc); + clean_up_bc(bc); dump_chan_list(stack); bc->pid = 0; cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data); @@ -1517,7 +1522,7 @@ void misdn_lib_release(struct misdn_bchannel *bc) empty_chan_in_stack(stack,bc->channel); empty_bc(bc); } - queue_cleanup_bc(bc); + clean_up_bc(bc); } @@ -2049,7 +2054,7 @@ 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) { @@ -2943,7 +2948,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) empty_chan_in_stack(stack,bc->channel); empty_bc(bc); - queue_cleanup_bc(bc); + clean_up_bc(bc); } /** we set it up later at RETRIEVE_ACK again.**/ @@ -3018,6 +3023,13 @@ int handle_err(msg_t *msg) case MGR_SETSTACK|INDICATION: return handle_bchan(msg); break; + + case MGR_SETSTACK|CONFIRM: + case MGR_CLEARSTACK|CONFIRM: + free_msg(msg) ; + return 1; + break; + case DL_DATA|INDICATION: { int port=(frm->addr&MASTER_ID_MASK) >> 8; @@ -3101,8 +3113,10 @@ int manager_isdn_handler(iframe_t *frm ,msg_t *msg) if (handle_l1(msg)) return 0 ; - /* The L2/L3 will be queued */ - if (queue_l2l3(msg)) + if (handle_frm_nt(msg)) + return 0; + + if (handle_frm(msg)) return 0; if (handle_err(msg)) @@ -3862,7 +3876,7 @@ void misdn_split_conf(struct misdn_bchannel *bc, int conf_id) } void misdn_lib_bridge( struct misdn_bchannel * bc1, struct misdn_bchannel *bc2) { - int conf_id=(bc1->pid<<1) +1; + int conf_id=bc1->pid +1; cb_log(1, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port); diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h index 98c40b03aed31acf483a499cbba166d4233769fb..a127c8f4ea2933e98bd02336a5ad28ed8aaa4463 100644 --- a/channels/misdn/isdn_lib.h +++ b/channels/misdn/isdn_lib.h @@ -182,7 +182,8 @@ struct misdn_bchannel { int l3_id; int pid; int ces; - + + int restart_channel; int channel; int channel_preselected; @@ -208,6 +209,10 @@ struct misdn_bchannel { /* get setup ack */ int need_more_infos; + /* may there be more infos ?*/ + int sending_complete; + + /* wether we should use jollys dsp or not */ int nodsp; diff --git a/channels/misdn/isdn_msg_parser.c b/channels/misdn/isdn_msg_parser.c index 0d5fb9f7251defce384502658569c1fab27a25bc..a11ffefe67b13318f7853347eb0353c9a36e02df 100644 --- a/channels/misdn/isdn_msg_parser.c +++ b/channels/misdn/isdn_msg_parser.c @@ -197,8 +197,8 @@ void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, } { - int sending_complete; - dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &sending_complete, nt,bc); + dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &bc->sending_complete, nt,bc); + } { @@ -217,6 +217,8 @@ void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, break; case 0: bc->capability=INFO_CAPABILITY_SPEECH; break; + case 18: bc->capability=INFO_CAPABILITY_VIDEO; + break; case 8: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED; bc->user1 = user; bc->urate = urate; @@ -775,7 +777,7 @@ void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *b { int exclusive, channel; - dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &channel, nt,bc); + dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc); if (channel==0xff) /* any channel */ channel=-1; cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n"); diff --git a/channels/misdn_config.c b/channels/misdn_config.c index d1c6111ef9873560a0fadc9b1c103a1a73a3ad38..58c1758bb88b401594677c1fee6a4b9bc908267e 100644 --- a/channels/misdn_config.c +++ b/channels/misdn_config.c @@ -84,6 +84,7 @@ struct misdn_cfg_spec { static const struct misdn_cfg_spec port_spec[] = { { "name", MISDN_CFG_GROUPNAME, MISDN_CTYPE_STR, "default", NONE }, + { "allowed_bearers", MISDN_CFG_ALLOWED_BEARERS, MISDN_CTYPE_STR, "all", NONE }, { "rxgain", MISDN_CFG_RXGAIN, MISDN_CTYPE_INT, "0", NONE }, { "txgain", MISDN_CFG_TXGAIN, MISDN_CTYPE_INT, "0", NONE }, { "te_choose_channel", MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CTYPE_BOOL, "no", NONE }, diff --git a/configs/misdn.conf.sample b/configs/misdn.conf.sample index cd382d55d229e726a8c6f42286ca9254982e2bbb..1f7dacc3890b36f426dd09b65585e424fd7a0afc 100644 --- a/configs/misdn.conf.sample +++ b/configs/misdn.conf.sample @@ -128,6 +128,11 @@ senddtmf=yes far_alerting=no +; +; here you can define which bearers should be allowed +; +allowed_bearers=all + ; Prefixes for national and international, those are put before the ; oad if an according dialplan is set by the other end. ;