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
This commit is contained in:
parent
9cac9bf42a
commit
77240a70d7
|
@ -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,45 +1425,94 @@ 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 <channel> \"<nr>\"\n"
|
||||
" Send CallDeflection to mISDN Channel.\n";
|
||||
e->command = "misdn send facility";
|
||||
e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \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];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue