started to add some basic support for supplementary services like CallForwarding...
authorChristian Richter <christian.richter@beronet.com>
Mon, 22 Oct 2007 10:04:04 +0000 (10:04 +0000)
committerChristian Richter <christian.richter@beronet.com>
Mon, 22 Oct 2007 10:04:04 +0000 (10:04 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@86616 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_misdn.c
channels/misdn/isdn_lib.c
channels/misdn/isdn_lib.h
channels/misdn/isdn_msg_parser.c

index a717baf..e90eff8 100644 (file)
@@ -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 <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];
 
-       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);
                }
index aacdc0b..a5e802b 100644 (file)
@@ -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");
                                                }
                                        }
                                }
index 43b9e3d..16dec8b 100644 (file)
@@ -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
index e9529a4..d055403 100644 (file)
@@ -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);
        }
 }