From 77240a70d7b73148c0a84c9133b953b90e53fead Mon Sep 17 00:00:00 2001 From: crichter Date: Mon, 22 Oct 2007 10:04:04 +0000 Subject: started to add some basic support for supplementary services like CallForwarding and so forth git-svn-id: http://svn.digium.com/svn/asterisk/trunk@86616 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_misdn.c | 202 +++++++++++++++++++++++++-------------- channels/misdn/isdn_lib.c | 43 +++++++-- channels/misdn/isdn_lib.h | 4 + channels/misdn/isdn_msg_parser.c | 2 +- 4 files changed, 169 insertions(+), 82 deletions(-) diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index a717bafe5..e90eff8c4 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -452,38 +452,46 @@ static char *bearer2str(int cap) { static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc) { switch (fac->Function) { - case Fac_CD: - chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber, - fac->u.CDeflection.PresentationAllowed ? "yes" : "no"); - break; - case Fac_AOCDCurrency: - if (fac->u.AOCDcur.chargeNotAvailable) - chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n"); - else if (fac->u.AOCDcur.freeOfCharge) - chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n"); - else if (fac->u.AOCDchu.billingId >= 0) - chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n", - fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier, - (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId); - else - chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n", - fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier, - (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total"); - break; - case Fac_AOCDChargingUnit: - if (fac->u.AOCDchu.chargeNotAvailable) - chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n"); - else if (fac->u.AOCDchu.freeOfCharge) - chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n"); - else if (fac->u.AOCDchu.billingId >= 0) - chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n", - fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId); - else - chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n", - fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total"); - break; - default: - chan_misdn_log(1,bc->port," --> unknown\n"); + case Fac_RESULT: + chan_misdn_log(0, bc->port," --> Received RESULT Operation\n"); + break; + case Fac_ERROR: + chan_misdn_log(0, bc->port," --> Received Error Operation\n"); + chan_misdn_log(0, bc->port," --> Value:%d Error:%s\n",fac->u.ERROR.errorValue, fac->u.ERROR.error); + break; + case Fac_CD: + chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber, + fac->u.CDeflection.PresentationAllowed ? "yes" : "no"); + break; + case Fac_AOCDCurrency: + if (fac->u.AOCDcur.chargeNotAvailable) + chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n"); + else if (fac->u.AOCDcur.freeOfCharge) + chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n"); + else if (fac->u.AOCDchu.billingId >= 0) + chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n", + fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier, + (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId); + else + chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n", + fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier, + (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total"); + break; + case Fac_AOCDChargingUnit: + if (fac->u.AOCDchu.chargeNotAvailable) + chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n"); + else if (fac->u.AOCDchu.freeOfCharge) + chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n"); + else if (fac->u.AOCDchu.billingId >= 0) + chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n", + fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId); + else + chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n", + fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total"); + break; + case Fac_None: + default: + chan_misdn_log(1,bc->port," --> unknown facility\n"); } } @@ -1417,44 +1425,93 @@ static char *handle_cli_misdn_show_port(struct ast_cli_entry *e, int cmd, struct return CLI_SUCCESS; } -static char *handle_cli_misdn_send_calldeflect(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { char *channame; char *nr; struct chan_list *tmp; - - switch (cmd) { + int port; + char *served_nr; + struct misdn_bchannel dummy, *bc=&dummy; + + switch (cmd) { case CLI_INIT: - e->command = "misdn send calldeflect"; - e->usage = - "Usage: misdn send calldeflect \"\"\n" - " Send CallDeflection to mISDN Channel.\n"; + e->command = "misdn send facility"; + e->usage = "Usage: misdn send facility \"\" \n" + "\t type is one of:\n" + "\t - calldeflect\n" + "\t - CFActivate\n" + "\t - CFDeactivate\n"; + return NULL; case CLI_GENERATE: return complete_ch(a); } - if (a->argc != 5) + if (a->argc < 5) return CLI_SHOWUSAGE; + + if (strstr(a->argv[3], "calldeflect")) { + if (a->argc < 6) { + ast_verbose("calldeflect requires 1 arg: ToNumber\n\n"); + return 0; + } + channame = a->argv[4]; + nr = a->argv[5]; - channame = a->argv[3]; - nr = a->argv[4]; + ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame); + tmp = get_chan_by_ast_name(channame); + if (!tmp) { + ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame); + return 0; + } - ast_cli(a->fd, "Sending Calldeflection (%s) to %s\n", nr, channame); - - tmp = get_chan_by_ast_name(channame); - if (!tmp) { - ast_cli(a->fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame); - return CLI_SUCCESS; - } + if (strlen(nr) >= 15) { + ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame); + return 0; + } + tmp->bc->fac_out.Function = Fac_CD; + ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber)); + misdn_lib_send_event(tmp->bc, EVENT_FACILITY); + } else if (strstr(a->argv[3],"CFActivate")) { + if (a->argc < 7) { + ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n"); + return 0; + } + port = atoi(a->argv[4]); + served_nr = a->argv[5]; + nr = a->argv[6]; - if (strlen(nr) >= 15) { - ast_cli(a->fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n", nr, channame); - return CLI_SUCCESS; + misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0); + + ast_verbose("Sending CFActivate Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr); + + bc->fac_out.Function = Fac_CFActivate; + bc->fac_out.u.CFActivate.BasicService = 0; //All Services + bc->fac_out.u.CFActivate.Procedure = 0; //Unconditional + ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber)); + ast_copy_string((char *)bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber)); + + misdn_lib_send_event(bc, EVENT_FACILITY); + } else if (strstr(a->argv[3],"CFDeactivate")) { + + if (a->argc < 6) { + ast_verbose("CFActivate requires 1 arg: FromNumber\n\n"); + return 0; + } + port = atoi(a->argv[4]); + served_nr = a->argv[5]; + + misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0); + ast_verbose("Sending CFDeactivate Port:(%d) FromNr. (%s)\n", port, served_nr); + + bc->fac_out.Function = Fac_CFDeactivate; + bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services + bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional + + ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber)); + misdn_lib_send_event(bc, EVENT_FACILITY); } - tmp->bc->fac_out.Function = Fac_CD; - ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber)); - misdn_lib_send_event(tmp->bc, EVENT_FACILITY); return CLI_SUCCESS; } @@ -1720,7 +1777,7 @@ static struct ast_cli_entry chan_misdn_clis[] = { AST_CLI(handle_cli_misdn_show_port, "Show detailed information for given port"), AST_CLI(handle_cli_misdn_show_ports_stats, "Show mISDNs channel's call statistics per port"), AST_CLI(handle_cli_misdn_show_stacks, "Show internal mISDN stack_list"), - AST_CLI(handle_cli_misdn_send_calldeflect, "Send CallDeflection to mISDN Channel"), + AST_CLI(handle_cli_misdn_send_facility, "Sends a Facility Message to the mISDN Channel"), AST_CLI(handle_cli_misdn_send_digit, "Send DTMF digit to mISDN Channel"), AST_CLI(handle_cli_misdn_send_display, "Send Text to mISDN Channel"), AST_CLI(handle_cli_misdn_send_restart, "Send a restart for every bchannel on the given port"), @@ -4850,17 +4907,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) break; case EVENT_FACILITY: - if (!ch) { - /* This may come from a call we don't know nothing about, so we ignore it. */ - chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n"); - break; - } - print_facility(&(bc->fac_in), bc); switch (bc->fac_in.Function) { + case Fac_RESULT: + break; case Fac_CD: - { + if (ch) { struct ast_channel *bridged = ast_bridged_channel(ch->ast); struct chan_list *ch_br; if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) { @@ -4879,17 +4932,24 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } break; case Fac_AOCDCurrency: - bc->AOCDtype = Fac_AOCDCurrency; - memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency)); - bc->AOCD_need_export = 1; - export_aoc_vars(ch->originator, ch->ast, bc); + if (ch) { + bc->AOCDtype = Fac_AOCDCurrency; + memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency)); + bc->AOCD_need_export = 1; + export_aoc_vars(ch->originator, ch->ast, bc); + } break; case Fac_AOCDChargingUnit: - bc->AOCDtype = Fac_AOCDChargingUnit; - memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit)); - bc->AOCD_need_export = 1; - export_aoc_vars(ch->originator, ch->ast, bc); + if (ch) { + bc->AOCDtype = Fac_AOCDChargingUnit; + memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit)); + bc->AOCD_need_export = 1; + export_aoc_vars(ch->originator, ch->ast, bc); + } break; + case Fac_None: + case Fac_ERROR: + break; default: chan_misdn_log(0, bc->port," --> not yet handled: facility type:%p\n", bc->fac_in.Function); } diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index aacdc0ba4..a5e802b9b 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -41,11 +41,27 @@ int misdn_lib_port_is_pri(int port) return -1; } -static void make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel) +int misdn_lib_port_is_nt(int port) +{ + struct misdn_stack *stack=get_misdn_stack(); + for ( ; stack; stack=stack->next) { + if (stack->port == port) { + return stack->nt; + } + } + + return -1; +} + +void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel) { memset (dummybc,0,sizeof(struct misdn_bchannel)); dummybc->port=port; - dummybc->l3_id=l3id; + if (l3id==0) + dummybc->l3_id = MISDN_ID_DUMMY; + else + dummybc->l3_id=l3id; + dummybc->nt=nt; dummybc->dummy=1; dummybc->channel=channel; @@ -1619,7 +1635,7 @@ static int handle_cr ( struct misdn_stack *stack, iframe_t *frm) if (!bc) { cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on this port.\n", frm->dinfo); - make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0); + misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0); bc=&dummybc; } @@ -1930,7 +1946,7 @@ handle_event_nt(void *dat, void *arg) /** removing procid **/ if (!bc) { cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x) on this port.\n", hh->dinfo); - make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0); + misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0); bc=&dummybc; } @@ -2029,7 +2045,7 @@ handle_event_nt(void *dat, void *arg) if (!bc) { cb_log(4, stack->port, " --> Didn't found BC so temporarly creating dummy BC (l3id:%x).\n", hh->dinfo); - make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0); + misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0); bc=&dummybc; } if (bc ) { @@ -2586,7 +2602,7 @@ static int handle_frm(msg_t *msg) bc=find_bc_by_l3id(stack, frm->dinfo); if (!bc && (frm->prim==(CC_RESTART|CONFIRM)) ) { - make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0); + misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0); bc=&dummybc; } @@ -2681,7 +2697,11 @@ handle_frm_bc: } else { struct misdn_bchannel dummybc; - cb_log(0, stack->port, " --> Didn't find BC so temporarly creating dummy BC (l3id:%x) on this port.\n", frm->dinfo); + if (frm->prim!=(CC_FACILITY|INDICATION)) + cb_log(0, stack->port, " --> Didn't find BC so temporarly creating dummy BC (l3id:%x) on this port.\n", frm->dinfo); + else + cb_log(5, stack->port, " --> Using Dummy BC for FACILITy\n"); + memset (&dummybc,0,sizeof(dummybc)); dummybc.port=stack->port; dummybc.l3_id=frm->dinfo; @@ -3673,7 +3693,7 @@ int misdn_lib_send_restart(int port, int channel) cb_log(0, port, "Sending Restarts on this port.\n"); - make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0); + misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0); /*if a channel is specified we restart only this one*/ if (channel > 0) { @@ -3825,10 +3845,13 @@ static void manager_event_handler(void *arg) if (bc) send_msg(glob_mgr->midev, bc, msg); else { - if (frm->dinfo == MISDN_ID_GLOBAL) { + if (frm->dinfo == MISDN_ID_GLOBAL || frm->dinfo == MISDN_ID_DUMMY ) { struct misdn_bchannel dummybc; - make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0); + cb_log(5,0," --> GLOBAL/DUMMY\n"); + misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0); send_msg(glob_mgr->midev, &dummybc, msg); + } else { + cb_log(0,0,"No bc for Message\n"); } } } diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h index 43b9e3dda..16dec8bb9 100644 --- a/channels/misdn/isdn_lib.h +++ b/channels/misdn/isdn_lib.h @@ -421,6 +421,7 @@ int misdn_lib_port_block(int port); int misdn_lib_port_unblock(int port); int misdn_lib_port_is_pri(int port); +int misdn_lib_port_is_nt(int port); int misdn_lib_port_up(int port, int notcheck); @@ -472,4 +473,7 @@ void bc_state_change(struct misdn_bchannel *bc, enum bchannel_state state); void misdn_dump_chanlist(void); +void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel); + + #endif diff --git a/channels/misdn/isdn_msg_parser.c b/channels/misdn/isdn_msg_parser.c index e9529a4c8..d05540373 100644 --- a/channels/misdn/isdn_msg_parser.c +++ b/channels/misdn/isdn_msg_parser.c @@ -965,7 +965,7 @@ static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bch err = decodeFac(p, &(bc->fac_in)); if (err) { - cb_log(1, bc->port, "Decoding FACILITY failed! (%d)\n", err); + cb_log(5, bc->port, "Decoding FACILITY failed! (%d)\n", err); } } -- cgit v1.2.3