X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=route.c;h=8217ff14ccf50d07a7ef61259945b042580dbdc1;hp=4fecf3854a1531da91d51135810fc9275611dbbd;hb=0eebd3a28e968844ec459298ac36e16305cc07bb;hpb=8994874d7bcb1eff9ee833fb22e4910cc365f456 diff --git a/route.c b/route.c index 4fecf38..8217ff1 100644 --- a/route.c +++ b/route.c @@ -68,8 +68,8 @@ struct cond_defs cond_defs[] = { "capability=speech|audio|video|digital-restricted|digital-unrestricted|digital-unrestricted-tones[,...]", "Matches the given bearer capability(s)."}, { "infolayer1", MATCH_INFOLAYER1, COND_TYPE_INTEGER, "infolayer1=[,...]", "Matches the given information layer 1. (2=u-Law, 3=a-law, see info layer 1 in bearer capability.)"}, - { "hlc", MATCH_HLC, COND_TYPE_INTEGER, - "hlc=[,...]", "Matches the high layer capability(s)."}, + { "hlc", MATCH_HLC, COND_TYPE_HLC, + "hlc=telephony|faxg2g3|faxg4|teletex1|teletex2|teletex3|videotex1|videotex2|telex|mhs|osi|maintenance|management|audiovisual[,...]", "Matches the high layer capability(s)."}, { "file", MATCH_FILE, COND_TYPE_STRING, "file=[,...]", "Mathes is the given file exists and if the first character is '1'."}, { "execute", MATCH_EXECUTE, COND_TYPE_STRING, @@ -126,11 +126,11 @@ struct param_defs param_defs[] = { "infolayer1", PARAM_TYPE_INTEGER, "infolayer1=", "Alter the layer 1 information of a call. Use 3 for ALAW or 2 for uLAW."}, { PARAM_HLC, - "hlc", PARAM_TYPE_INTEGER, - "hlc=", "Alter the HLC identification. Use 1 for telephony or omit."}, + "hlc", PARAM_TYPE_HLC, + "hlc=telephony|faxg2g3|faxg4|teletex1|teletex2|teletex3|videotex1|videotex2|telex|mhs|osi|maintenance|management|audiovisual", "Alter the HLC identification."}, { PARAM_EXTHLC, - "exthlc", PARAM_TYPE_INTEGER, - "exthlc=", "Alter extended HLC value. (Mainenance only, don't use it.)"}, + "exthlc", PARAM_TYPE_HLC, + "exthlc=", "Alter extended HLC value, see hlc. (Mainenance only, don't use it.)"}, { PARAM_PRESENT, "present", PARAM_TYPE_YESNO, "present=yes|no", "Allow or restrict caller ID regardless what the caller wants."}, @@ -242,13 +242,16 @@ struct param_defs param_defs[] = { { PARAM_ON, "on", PARAM_TYPE_STRING, "on=[init|hangup]", "Defines if the action is executed on call init or on hangup."}, + { PARAM_KEYPAD, + "keypad", PARAM_TYPE_NULL, + "keypad", "Use 'keypad facility' for dialing, instead of 'called number'."}, { 0, NULL, 0, NULL, NULL} }; struct action_defs action_defs[] = { { ACTION_EXTERNAL, "extern", &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, + 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_KEYPAD | PARAM_TIMEOUT, "Call is routed to extern number as dialed."}, { ACTION_INTERNAL, "intern", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_internal, &EndpointAppPBX::action_hangup_call, @@ -256,7 +259,7 @@ struct action_defs action_defs[] = { "Call is routed to intern extension as given by the dialed number or specified by option."}, { ACTION_OUTDIAL, "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, + 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_KEYPAD | PARAM_TIMEOUT, "Same as 'extern'"}, { ACTION_REMOTE, "remote", &EndpointAppPBX::action_init_remote, &EndpointAppPBX::action_dialing_remote, &EndpointAppPBX::action_hangup_call, @@ -339,6 +342,10 @@ 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_RELEASE, + "release", NULL, &EndpointAppPBX::action_dialing_release, NULL, + PARAM_CONNECT | PARAM_CAUSE | PARAM_LOCATION | PARAM_DISPLAY, + "Same as 'disconnect', but using RELEASE message on ISDN."}, { ACTION_DEFLECT, "deflect", NULL, &EndpointAppPBX::action_dialing_deflect, NULL, PARAM_DEST, @@ -351,7 +358,7 @@ struct action_defs action_defs[] = { // "The call forward is set within the telephone network of the external line."}, { ACTION_EXECUTE, "execute", &EndpointAppPBX::action_init_execute, NULL, &EndpointAppPBX::action_hangup_execute, - PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM | PARAM_ON, + PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM | PARAM_ON | PARAM_TIMEOUT, "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, @@ -1245,6 +1252,43 @@ struct route_ruleset *ruleset_parse(void) cond->value_type = VALUE_TYPE_INTEGER; break; + /* parse service value */ + case COND_TYPE_HLC: + if (!strncasecmp("telephony", p, 9)) + cond->integer_value = INFO_HLC_TELEPHONY; + else if (!strncasecmp("faxg2g3", p, 7)) + cond->integer_value = INFO_HLC_FAXG2G3; + else if (!strncasecmp("faxg4", p, 5)) + cond->integer_value = INFO_HLC_FAXG4; + else if (!strncasecmp("teletex1", p, 8)) + cond->integer_value = INFO_HLC_TELETEX1; + else if (!strncasecmp("teletex2", p, 8)) + cond->integer_value = INFO_HLC_TELETEX2; + else if (!strncasecmp("teletex3", p, 8)) + cond->integer_value = INFO_HLC_TELETEX3; + else if (!strncasecmp("videotex1", p, 9)) + cond->integer_value = INFO_HLC_VIDEOTEX1; + else if (!strncasecmp("videotex2", p, 9)) + cond->integer_value = INFO_HLC_VIDEOTEX2; + else if (!strncasecmp("telex", p, 5)) + cond->integer_value = INFO_HLC_TELEX; + else if (!strncasecmp("mhs", p, 3)) + cond->integer_value = INFO_HLC_MHS; + else if (!strncasecmp("osi", p, 3)) + cond->integer_value = INFO_HLC_OSI; + else if (!strncasecmp("maintenance", p, 11)) + cond->integer_value = INFO_HLC_MAINTENANCE; + else if (!strncasecmp("management", p, 10)) + cond->integer_value = INFO_HLC_MANAGEMENT; + else if (!strncasecmp("audiovisual", p, 11)) + cond->integer_value = INFO_HLC_AUDIOVISUAL; + else { + SPRINT(failure, "Given HLC type is invalid or misspelled."); + goto parse_error; + } + cond->value_type = VALUE_TYPE_INTEGER; + break; + /* parse interface attribute : */ case COND_TYPE_IFATTR: key[0] = key_to[0] = '\0'; @@ -1529,6 +1573,7 @@ struct route_ruleset *ruleset_parse(void) case PARAM_TYPE_CALLERIDTYPE: case PARAM_TYPE_CAPABILITY: case PARAM_TYPE_BMODE: + case PARAM_TYPE_HLC: case PARAM_TYPE_DIVERSION: case PARAM_TYPE_DESTIN: case PARAM_TYPE_TYPE: @@ -1620,6 +1665,67 @@ struct route_ruleset *ruleset_parse(void) SPRINT(failure, "Bchannel mode '%s' unknown.", key); goto parse_error; } + if (param_defs[index].type == PARAM_TYPE_HLC) { + param->value_type = VALUE_TYPE_INTEGER; + if (!strcasecmp(key, "telephony")) { + param->integer_value = INFO_HLC_TELEPHONY; + break; + } + if (!strcasecmp(key, "faxg2g3")) { + param->integer_value = INFO_HLC_FAXG2G3; + break; + } + if (!strcasecmp(key, "faxg4")) { + param->integer_value = INFO_HLC_FAXG4; + break; + } + if (!strcasecmp(key, "teletex1")) { + param->integer_value = INFO_HLC_TELETEX1; + break; + } + if (!strcasecmp(key, "teletex2")) { + param->integer_value = INFO_HLC_TELETEX2; + break; + } + if (!strcasecmp(key, "teletex3")) { + param->integer_value = INFO_HLC_TELETEX3; + break; + } + if (!strcasecmp(key, "videotex1")) { + param->integer_value = INFO_HLC_VIDEOTEX1; + break; + } + if (!strcasecmp(key, "videotex2")) { + param->integer_value = INFO_HLC_VIDEOTEX2; + break; + } + if (!strcasecmp(key, "telex")) { + param->integer_value = INFO_HLC_TELEX; + break; + } + if (!strcasecmp(key, "mhs")) { + param->integer_value = INFO_HLC_MHS; + break; + } + if (!strcasecmp(key, "osi")) { + param->integer_value = INFO_HLC_OSI; + break; + } + if (!strcasecmp(key, "maintenance")) { + param->integer_value = INFO_HLC_MAINTENANCE; + break; + } + if (!strcasecmp(key, "management")) { + param->integer_value = INFO_HLC_MANAGEMENT; + break; + } + if (!strcasecmp(key, "audiovisual")) { + param->integer_value = INFO_HLC_AUDIOVISUAL; + break; + } + SPRINT(failure, "HLC type '%s' unknown.", key); + goto parse_error; + } if (param_defs[index].type == PARAM_TYPE_DIVERSION) { param->value_type = VALUE_TYPE_INTEGER; if (!strcasecmp(key, "cfu")) { @@ -1784,16 +1890,21 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) struct route_action *action = NULL; unsigned long comp_len; int j, jj; + char isdn_port[10]; + char *argv[11]; /* check also number of args below */ char callerid[64], callerid2[64], redirid[64]; int integer; char *string; FILE *tfp; - double timeout; + long long timeout, now_ll = 0, match_timeout = 0; + struct timeval current_time; struct mISDNport *mISDNport; struct admin_list *admin; + time_t now; + struct tm *now_tm; + int pid2; /* reset timeout action */ - e_match_timeout = 0; /* no timeout */ e_match_to_action = NULL; SCPY(callerid, numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international)); @@ -1845,7 +1956,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) goto match_string_prefix; case MATCH_EXTENSION: - string = e_ext.name; + string = e_ext.number; goto match_string; case MATCH_DIALING: @@ -1907,22 +2018,32 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) goto match_string_prefix; case MATCH_TIME: + time(&now); + now_tm = localtime(&now); integer = now_tm->tm_hour*100 + now_tm->tm_min; goto match_integer; case MATCH_MDAY: + time(&now); + now_tm = localtime(&now); integer = now_tm->tm_mday; goto match_integer; case MATCH_MONTH: + time(&now); + now_tm = localtime(&now); integer = now_tm->tm_mon+1; goto match_integer; case MATCH_YEAR: + time(&now); + now_tm = localtime(&now); integer = now_tm->tm_year + 1900; goto match_integer; case MATCH_WDAY: + time(&now); + now_tm = localtime(&now); integer = now_tm->tm_wday; integer = integer?integer:7; /* correct sunday */ goto match_integer; @@ -1950,8 +2071,26 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) break; case MATCH_EXECUTE: - if (system(cond->string_value) == 0) - istrue = 1; + j = 0; +#if 0 + argv[j++] = (char *)"/bin/sh"; + argv[j++] = (char *)"-c"; + argv[j++] = cond->string_value; +#endif + argv[j++] = cond->string_value; + argv[j++] = e_extdialing; + argv[j++] = (char *)numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international); + argv[j++] = e_callerinfo.extension; + argv[j++] = e_callerinfo.name; + SPRINT(isdn_port, "%d", e_callerinfo.isdn_port); + argv[j++] = isdn_port; + argv[j++] = e_callerinfo.imsi; + argv[j++] = NULL; /* check also number of args above */ + if (fork() == 0) { + if ((pid2 = fork()) == 0) { + execve(cond->string_value, argv, environ); + } + } break; case MATCH_DEFAULT: @@ -1960,7 +2099,11 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) break; case MATCH_TIMEOUT: - timeout = now_d + cond->integer_value; + if (!now_ll) { + gettimeofday(¤t_time, NULL); + now_ll = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec; + } + timeout = now_ll + (cond->integer_value * MICRO_SECONDS); istrue = 1; break; @@ -2163,10 +2306,10 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) cond = cond->next; } - if (timeout>now_d && match==1) /* the matching rule with timeout in the future */ - if (e_match_timeout<1 || timeoutnow_ll && match==1) /* the matching rule with timeout in the future */ + if (match_timeout == 0 || timeout < match_timeout) { /* first timeout or lower */ /* set timeout in the furture */ - e_match_timeout = timeout; + match_timeout = timeout; e_match_to_action = rule->action_first; e_match_to_extdialing = e_dialinginfo.id + dialing_required; match = 0; /* matches in the future */ @@ -2174,7 +2317,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) if (match == 1) { /* matching, we return first action */ action = rule->action_first; - e_match_timeout = 0; /* no timeout */ + match_timeout = 0; /* no timeout */ e_match_to_action = NULL; e_extdialing = e_dialinginfo.id + dialing_required; break; @@ -2185,6 +2328,11 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) } rule = rule->next; } + if (match_timeout == 0) + unsched_timer(&e_match_timeout); /* no timeout */ + else { + schedule_timer(&e_match_timeout, match_timeout / 1000000, match_timeout % 1000000); + } return(action); }