X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=route.c;h=da59e987b806d78945b5b6333a0f1d75dd968afc;hp=97c61a6555fa3b8bfc56b6fb48f8cfa13aa2d29b;hb=6bf7c7f9db360d6031417b012dcb0e90e2251cd6;hpb=3754d8f73ff7cb55e204f7ede6569028407a00e5 diff --git a/route.c b/route.c index 97c61a6..da59e98 100644 --- a/route.c +++ b/route.c @@ -9,10 +9,6 @@ ** ** \*****************************************************************************/ -#include -#include -#include -#include #include "main.h" @@ -30,6 +26,8 @@ struct cond_defs cond_defs[] = { "interface=[,...]", "Matches if call is received from given interface(s). NOT PORTS!"}, { "callerid", MATCH_CALLERID, COND_TYPE_STRING, "callerid=[-][,...]", "Matches if caller ID matches or begins with the given (range(s) of) prefixes(s)."}, + { "callerid2", MATCH_CALLERID2,COND_TYPE_STRING, + "callerid2=[-][,...]", "Matches the second caller ID (network provided)."}, { "extension", MATCH_EXTENSION,COND_TYPE_STRING, "extension=[-][,...]", "Matches if caller calls from given (range(s) of) extension(s)."}, { "dialing", MATCH_DIALING, COND_TYPE_STRING, @@ -91,7 +89,11 @@ struct cond_defs cond_defs[] = { { "busy", MATCH_BUSY, COND_TYPE_STRING, "busy=[,...]","Matches if any of the given extension is busy."}, { "notbusy", MATCH_IDLE, COND_TYPE_STRING, - "notbusy[,...]","Matches if any of the given extension is not busy."}, + "notbusy=[,...]","Matches if any of the given extension is not busy."}, + { "remote", MATCH_REMOTE, COND_TYPE_STRING, + "remote=","Matches if remote application is running."}, + { "notremote", MATCH_NOTREMOTE,COND_TYPE_STRING, + "notremote=","Matches if remote application is not running."}, { NULL, 0, 0, NULL} }; @@ -119,7 +121,7 @@ struct param_defs param_defs[] = { "capability=speech|audio|video|digital-restricted|digital-unrestricted|digital-unrestricted-tones", "Alter the service type of the call."}, { PARAM_BMODE, "bmode", PARAM_TYPE_BMODE, - "capability=transparent|hdlc", "Alter the bchannel mode of the call. Use hdlc for data calls."}, + "bmode=transparent|hdlc", "Alter the bchannel mode of the call. Use hdlc for data calls."}, { PARAM_INFO1, "infolayer1", PARAM_TYPE_INTEGER, "infolayer1=", "Alter the layer 1 information of a call. Use 3 for ALAW or 2 for uLAW."}, @@ -216,6 +218,9 @@ struct param_defs param_defs[] = { { PARAM_ROOM, "room", PARAM_TYPE_INTEGER, "room=", "Conference room number, must be greater 0, as in real life."}, + { PARAM_JINGLE, + "jingle", PARAM_TYPE_NULL, + "jingle", "Conference members will hear a jingle if a member joins."}, { PARAM_TIMEOUT, "timeout", PARAM_TYPE_INTEGER, "timeout=", "Timeout before continue with next action."}, @@ -225,6 +230,18 @@ struct param_defs param_defs[] = { { PARAM_STRIP, "strip", PARAM_TYPE_NULL, "strip", "Remove digits that were required to match this rule."}, + { PARAM_APPLICATION, + "application",PARAM_TYPE_STRING, + "application=", "Name of remote application to make call to."}, + { PARAM_CONTEXT, + "context", PARAM_TYPE_STRING, + "context=", "Give context parameter to the remote application."}, + { PARAM_EXTEN, + "exten", PARAM_TYPE_STRING, + "exten=", "Give exten parameter to the remote application. (overrides dialed number)"}, + { PARAM_ON, + "on", PARAM_TYPE_STRING, + "on=[init|hangup]", "Defines if the action is executed on call init or on hangup."}, { 0, NULL, 0, NULL, NULL} }; @@ -241,17 +258,17 @@ struct action_defs action_defs[] = { "outdial", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call, PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_TIMEOUT, "Same as 'extern'"}, - { ACTION_CHAN, - "asterisk", &EndpointAppPBX::action_init_chan, &EndpointAppPBX::action_dialing_chan, &EndpointAppPBX::action_hangup_call, - PARAM_CONNECT | PARAM_TIMEOUT, - "Call is routed to Asterisk via channel driver."}, + { ACTION_REMOTE, + "remote", &EndpointAppPBX::action_init_remote, &EndpointAppPBX::action_dialing_remote, &EndpointAppPBX::action_hangup_call, + PARAM_CONNECT | PARAM_APPLICATION | PARAM_CONTEXT | PARAM_EXTEN | PARAM_TIMEOUT, + "Call is routed to Remote application, like Asterisk."}, { ACTION_VBOX_RECORD, "vbox-record",&EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_vbox_record, &EndpointAppPBX::action_hangup_call, PARAM_CONNECT | PARAM_EXTENSION | PARAM_ANNOUNCEMENT | PARAM_TIMEOUT, "Caller is routed to the voice box of given extension."}, { ACTION_PARTYLINE, "partyline",&EndpointAppPBX::action_init_partyline, NULL, &EndpointAppPBX::action_hangup_call, - PARAM_ROOM, + PARAM_ROOM | PARAM_JINGLE, "Caller is participating the conference with the given room number."}, { ACTION_LOGIN, "login", NULL, &EndpointAppPBX::action_dialing_login, NULL, @@ -276,7 +293,7 @@ struct action_defs action_defs[] = { { ACTION_REPLY, "reply", &EndpointAppPBX::action_init_redial_reply, &EndpointAppPBX::action_dialing_reply, NULL, PARAM_CONNECT | PARAM_SELECT, - "Caller replies. (last incomming call(s))"}, + "Caller replies. (last incoming call(s))"}, { ACTION_POWERDIAL, "powerdial", NULL, &EndpointAppPBX::action_dialing_powerdial, NULL, PARAM_CONNECT | PARAM_DELAY | PARAM_LIMIT | PARAM_TIMEOUT, @@ -312,7 +329,7 @@ struct action_defs action_defs[] = { // "Caller calls the timer."}, { ACTION_GOTO, "goto", NULL, &EndpointAppPBX::action_dialing_goto, NULL, - PARAM_CONNECT | PARAM_RULESET | PARAM_STRIP | PARAM_SAMPLE, + PARAM_PROCEEDING | PARAM_ALERTING | PARAM_CONNECT | PARAM_RULESET | PARAM_STRIP | PARAM_SAMPLE, "Jump to given ruleset and optionally play sample. Dialed digits are not flushed."}, { ACTION_MENU, "menu", NULL, &EndpointAppPBX::action_dialing_menu, NULL, @@ -322,11 +339,6 @@ struct action_defs action_defs[] = { "disconnect", NULL, &EndpointAppPBX::action_dialing_disconnect, NULL, PARAM_CONNECT | PARAM_CAUSE | PARAM_LOCATION | PARAM_SAMPLE | PARAM_DISPLAY, "Caller gets disconnected optionally with given cause and given sample and given display text."}, - { ACTION_HELP, - "help", NULL, &EndpointAppPBX::action_dialing_help, NULL, - PARAM_CONNECT | PARAM_TIMEOUT, - NULL}, -// "Caller will be able to select from current rules that would match. (using * and #)"}, { ACTION_DEFLECT, "deflect", NULL, &EndpointAppPBX::action_dialing_deflect, NULL, PARAM_DEST, @@ -338,8 +350,8 @@ struct action_defs action_defs[] = { NULL}, // "The call forward is set within the telephone network of the external line."}, { ACTION_EXECUTE, - "execute", NULL, NULL, &EndpointAppPBX::action_hangup_execute, - PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM, + "execute", &EndpointAppPBX::action_init_execute, NULL, &EndpointAppPBX::action_hangup_execute, + PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM | PARAM_ON, "Executes the given script file. The file must terminate quickly, because it will halt the PBX."}, { ACTION_FILE, "file", NULL, NULL, &EndpointAppPBX::action_hangup_file, @@ -477,16 +489,16 @@ void ruleset_free(struct route_ruleset *ruleset_start) cond = rule->cond_first; if (cond->string_value) { - free(cond->string_value); + FREE(cond->string_value, 0); rmemuse--; } if (cond->string_value_to) { - free(cond->string_value_to); + FREE(cond->string_value_to, 0); rmemuse--; } rule->cond_first = cond->next; - free(cond); + FREE(cond, sizeof(struct route_cond)); rmemuse--; } while(rule->action_first) @@ -499,19 +511,19 @@ void ruleset_free(struct route_ruleset *ruleset_start) action->param_first = param->next; if (param->string_value) { - free(param->string_value); + FREE(param->string_value, 0); rmemuse--; } - free(param); + FREE(param, sizeof(struct route_param)); rmemuse--; } - free(action); + FREE(action, sizeof(struct route_action)); rmemuse--; } - free(rule); + FREE(rule, sizeof(struct route_rule)); rmemuse--; } - free(ruleset); + FREE(ruleset, sizeof(struct route_ruleset)); rmemuse--; } } @@ -744,7 +756,7 @@ void ruleset_debug(struct route_ruleset *ruleset_start) /* * parse ruleset */ -static char *read_string(char *p, char *key, int key_size, char *special) +static char *read_string(char *p, char *key, int key_size, const char *special) { key[0] = 0; @@ -841,6 +853,7 @@ struct route_ruleset *ruleset_parse(void) struct route_param *param; struct route_param **param_pointer = NULL; char failure[256]; + unsigned long long allowed_params; /* check the integrity of IDs for ACTION_* and PARAM_* */ i = 0; @@ -867,7 +880,7 @@ struct route_ruleset *ruleset_parse(void) j<<=1; } - SPRINT(filename[0], "%s/routing.conf", INSTALL_DATA); + SPRINT(filename[0], "%s/routing.conf", CONFIG_DATA); if (!(fp[0]=fopen(filename[0],"r"))) { @@ -935,7 +948,7 @@ struct route_ruleset *ruleset_parse(void) if (key[0] == '/') SCPY(filename[nesting+1], key); else - SPRINT(filename[nesting+1], "%s/%s", INSTALL_DATA, key); + SPRINT(filename[nesting+1], "%s/%s", CONFIG_DATA, key); if (!(fp[nesting+1]=fopen(filename[nesting+1],"r"))) { PERROR("Cannot open %s\n", filename[nesting+1]); @@ -966,7 +979,7 @@ struct route_ruleset *ruleset_parse(void) /* reading ruleset name text */ i = 0; - while((*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9')) + while(*p>' ' && *p<127 && *p!=']') { if (*p>='A' && *p<='Z') *p = *p-'A'+'a'; /* lower case */ key[i++] = *p++; @@ -1002,14 +1015,8 @@ struct route_ruleset *ruleset_parse(void) } /* create ruleset */ - ruleset = (struct route_ruleset *)malloc(sizeof(struct route_ruleset)); - if (ruleset == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + ruleset = (struct route_ruleset *)MALLOC(sizeof(struct route_ruleset)); rmemuse++; - memset(ruleset, 0, sizeof(struct route_ruleset)); *ruleset_pointer = ruleset; ruleset_pointer = &(ruleset->next); SCPY(ruleset->name, key); @@ -1026,15 +1033,9 @@ struct route_ruleset *ruleset_parse(void) goto new_ruleset; } - /* alloc memory for rule */ - rule = (struct route_rule *)malloc(sizeof(struct route_rule)); - if (rule == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + /* Alloc memory for rule */ + rule = (struct route_rule *)MALLOC(sizeof(struct route_rule)); rmemuse++; - memset(rule, 0, sizeof(struct route_rule)); *rule_pointer = rule; rule_pointer = &(rule->next); cond_pointer = &(rule->cond_first); @@ -1121,15 +1122,9 @@ struct route_ruleset *ruleset_parse(void) } nextcondvalue: - /* alloc memory for item */ - cond = (struct route_cond *)malloc(sizeof(struct route_cond)); - if (cond == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + /* Alloc memory for item */ + cond = (struct route_cond *)MALLOC(sizeof(struct route_cond)); rmemuse++; - memset(cond, 0, sizeof(struct route_cond)); *cond_pointer = cond; cond_pointer = &(cond->next); cond->index = index; @@ -1314,22 +1309,12 @@ struct route_ruleset *ruleset_parse(void) } } alloc_string: - cond->string_value = (char *)malloc(strlen(key)+1); - if (cond->string_value == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + cond->string_value = (char *)MALLOC(strlen(key)+1); rmemuse++; UCPY(cond->string_value, key); if (value_type == VALUE_TYPE_STRING_RANGE) { - cond->string_value_to = (char *)malloc(strlen(key_to)+1); - if (cond->string_value_to == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + cond->string_value_to = (char *)MALLOC(strlen(key_to)+1); rmemuse++; UCPY(cond->string_value_to, key_to); cond->comp_string = strcmp(key, key_to); @@ -1482,16 +1467,11 @@ struct route_ruleset *ruleset_parse(void) SPRINT(failure, "Unknown action name '%s'.", key); goto parse_error; } + allowed_params = action_defs[index].params; /* alloc memory for action */ - action = (struct route_action *)malloc(sizeof(struct route_action)); - if (action == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + action = (struct route_action *)MALLOC(sizeof(struct route_action)); rmemuse++; - memset(action, 0, sizeof(struct route_action)); *action_pointer = action; action_pointer = &(action->next); param_pointer = &(action->param_first); @@ -1537,6 +1517,13 @@ struct route_ruleset *ruleset_parse(void) goto parse_error; } + /* check if item is allowed for the action */ + if (!(param_defs[index].id & allowed_params)) + { + SPRINT(failure, "Param name '%s' exists, but not for this action.", key); + goto parse_error; + } + /* params without values must not have any parameter */ if (param_defs[index].type == PARAM_TYPE_NULL) { @@ -1619,15 +1606,9 @@ struct route_ruleset *ruleset_parse(void) } nextparamvalue: - /* alloc memory for param */ - param = (struct route_param *)malloc(sizeof(struct route_param)); - if (param == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + /* Alloc memory for param */ + param = (struct route_param *)MALLOC(sizeof(struct route_param)); rmemuse++; - memset(param, 0, sizeof(struct route_param)); *param_pointer = param; param_pointer = &(param->next); param->index = index; @@ -1706,6 +1687,7 @@ struct route_ruleset *ruleset_parse(void) case PARAM_TYPE_DESTIN: case PARAM_TYPE_TYPE: case PARAM_TYPE_YESNO: + case PARAM_TYPE_ON: key[0] = '\0'; if (*p==',' || *p==' ' || *p=='\0') { @@ -1744,6 +1726,22 @@ struct route_ruleset *ruleset_parse(void) SPRINT(failure, "Caller ID type '%s' unknown.", key); goto parse_error; } + if (param_defs[index].type == PARAM_TYPE_ON) + { + param->value_type = VALUE_TYPE_INTEGER; + if (!strcasecmp(key, "init")) + { + param->integer_value = INFO_ON_INIT; + break; + } + if (!strcasecmp(key, "hangup")) + { + param->integer_value = INFO_ON_HANGUP; + break; + } + SPRINT(failure, "Execute on '%s' unknown.", key); + goto parse_error; + } if (param_defs[index].type == PARAM_TYPE_CAPABILITY) { param->value_type = VALUE_TYPE_INTEGER; @@ -1864,12 +1862,7 @@ struct route_ruleset *ruleset_parse(void) SPRINT(failure, "Value '%s' unknown. ('yes' or 'no')", key); goto parse_error; } - param->string_value = (char *)malloc(strlen(key)+1); - if (param->string_value == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + param->string_value = (char *)MALLOC(strlen(key)+1); rmemuse++; UCPY(param->string_value, key); param->value_type = VALUE_TYPE_STRING; @@ -1951,7 +1944,7 @@ struct route_ruleset *ruleset_parse(void) /* * return ruleset by name */ -struct route_ruleset *getrulesetbyname(char *name) +struct route_ruleset *getrulesetbyname(const char *name) { struct route_ruleset *ruleset = ruleset_first; @@ -1985,19 +1978,21 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) struct route_action *action = NULL; unsigned long comp_len; int j, jj; - char callerid[64], redirid[64]; + char callerid[64], callerid2[64], redirid[64]; int integer; char *string; FILE *tfp; double timeout; struct mISDNport *mISDNport; + struct admin_list *admin; /* reset timeout action */ e_match_timeout = 0; /* no timeout */ e_match_to_action = NULL; - SCPY(callerid, numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype)); - SCPY(redirid, numberrize_callerinfo(e_redirinfo.id, e_redirinfo.ntype)); + SCPY(callerid, numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international)); + SCPY(callerid2, numberrize_callerinfo(e_callerinfo.id2, e_callerinfo.ntype2, options.national, options.international)); + SCPY(redirid, numberrize_callerinfo(e_redirinfo.id, e_redirinfo.ntype, options.national, options.international)); PDEBUG(DEBUG_ROUTE, "parsing ruleset '%s'\n", ruleset->name); while(rule) @@ -2027,7 +2022,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) case MATCH_PORT: if (ea_endpoint->ep_portlist) - if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1) + if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_MASK) != PORT_CLASS_mISDN) break; integer = e_callerinfo.isdn_port; goto match_integer; @@ -2042,6 +2037,10 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) string = callerid; goto match_string_prefix; + case MATCH_CALLERID2: + string = callerid2; + goto match_string_prefix; + case MATCH_EXTENSION: string = e_ext.name; goto match_string; @@ -2091,12 +2090,12 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) break; case MATCH_REDIRECTED: - if (e_redirinfo.present != INFO_PRESENT_NULL) + if (e_redirinfo.ntype != INFO_NTYPE_NOTPRESENT) istrue = 1; break; case MATCH_DIRECT: - if (e_redirinfo.present == INFO_PRESENT_NULL) + if (e_redirinfo.ntype == INFO_NTYPE_NOTPRESENT) istrue = 1; break; @@ -2175,7 +2174,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) if (mISDNport->ifport) if (strlen(mISDNport->ifport->interface->name) == comp_len) if (!strncasecmp(mISDNport->ifport->interface->name, cond->string_value, comp_len)) - if (!mISDNport->ptp || mISDNport->l2link) + if (!mISDNport->l2hold || mISDNport->l2link>0) { j = 0; jj = mISDNport->b_num; @@ -2207,7 +2206,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) { if (mISDNport->ifport) if (!strcasecmp(mISDNport->ifport->interface->name, cond->string_value)) - if (!mISDNport->ptp || mISDNport->l2link) /* break if one is up */ + if (!mISDNport->l2hold || mISDNport->l2link>0) break; mISDNport = mISDNport->next; } @@ -2221,7 +2220,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) { if (mISDNport->ifport) if (!strcasecmp(mISDNport->ifport->interface->name, cond->string_value)) - if (!mISDNport->ptp || mISDNport->l2link) /* break if one is up */ + if (!mISDNport->l2hold || mISDNport->l2link>0) break; mISDNport = mISDNport->next; @@ -2231,6 +2230,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) break; case MATCH_BUSY: + case MATCH_IDLE: any = 0; mISDNport = mISDNport_first; while(mISDNport) @@ -2241,21 +2241,24 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) break; mISDNport = mISDNport->next; } - if (mISDNport) + if (mISDNport && cond->match==MATCH_BUSY) + istrue = 1; + if (!mISDNport && cond->match==MATCH_IDLE) istrue = 1; break; - case MATCH_IDLE: - mISDNport = mISDNport_first; - while(mISDNport) + case MATCH_REMOTE: + case MATCH_NOTREMOTE: + admin = admin_first; + while(admin) { - if (mISDNport->ifport) - if (!strcasecmp(mISDNport->ifport->interface->name, cond->string_value)) - if (mISDNport->use) /* break if in use */ + if (admin->remote_name[0] && !strcmp(cond->string_value, admin->remote_name)) break; - mISDNport = mISDNport->next; + admin = admin->next; } - if (!mISDNport) + if (admin && cond->match==MATCH_REMOTE) + istrue = 1; + if (!admin && cond->match==MATCH_NOTREMOTE) istrue = 1; break; @@ -2461,10 +2464,10 @@ struct route_action action_internal = { 0, }; -struct route_action action_chan = { +struct route_action action_remote = { NULL, NULL, - ACTION_CHAN, + ACTION_REMOTE, 0, 0, };