X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=route.c;h=7954b6feeb7d513914cb4725745bc8c9c6982056;hp=4fecf3854a1531da91d51135810fc9275611dbbd;hb=acaf278f7f616d264afe480e4f9c64768540941b;hpb=b987a1bbbcabbf183ebe009903778671a1591337 diff --git a/route.c b/route.c index 4fecf38..7954b6f 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, @@ -94,6 +94,14 @@ struct cond_defs cond_defs[] = { "remote=","Matches if remote application is running."}, { "notremote", MATCH_NOTREMOTE,COND_TYPE_STRING, "notremote=","Matches if remote application is not running."}, + { "pots-flash", MATCH_POTS_FLASH,COND_TYPE_NULL, + "pots-flash","When using POTS: Matches if call was invoked by flash/earth button."}, + { "pots-cw", MATCH_POTS_CW, COND_TYPE_NULL, + "pots-cw","When using POTS: Matches if a call is waiting."}, + { "pots-calls", MATCH_POTS_CALLS,COND_TYPE_INTEGER, + "pots-calls=","When using POTS: Matches if given number of calls are held."}, + { "pots-last", MATCH_POTS_LAST,COND_TYPE_INTEGER, + "pots-last=","When using POTS: Matches if given call number (1=oldest) was the last active call."}, { NULL, 0, 0, NULL} }; @@ -126,11 +134,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 +250,19 @@ 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'."}, + { PARAM_POTS_CALL, + "pots-call", PARAM_TYPE_INTEGER, + "pots-call=", "Select call number. The oldest call is number 1."}, { 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_CONTEXT | 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,12 +270,8 @@ 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, - 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, @@ -339,6 +349,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 +365,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, @@ -377,6 +391,30 @@ struct action_defs action_defs[] = { "efi", &EndpointAppPBX::action_init_efi, NULL, NULL, PARAM_PROCEEDING | PARAM_ALERTING | PARAM_CONNECT, "Elektronische Fernsprecher Identifikation - announces caller ID."}, + { ACTION_POTS_RETRIEVE, + "pots-retrieve", &EndpointAppPBX::action_init_pots_retrieve, NULL, NULL, + PARAM_POTS_CALL, + "When using POTS: Select call on hold to retrieve."}, + { ACTION_POTS_RELEASE, + "pots-release", &EndpointAppPBX::action_init_pots_release, NULL, NULL, + PARAM_POTS_CALL, + "When using POTS: Select call on hold to release."}, + { ACTION_POTS_REJECT, + "pots-reject", &EndpointAppPBX::action_init_pots_reject, NULL, NULL, + 0, + "When using POTS: Reject incomming waiting call."}, + { ACTION_POTS_ANSWER, + "pots-answer", &EndpointAppPBX::action_init_pots_answer, NULL, NULL, + 0, + "When using POTS: Answer incomming waiting call."}, + { ACTION_POTS_3PTY, + "pots-3pty", &EndpointAppPBX::action_init_pots_3pty, NULL, NULL, + 0, + "When using POTS: Invoke 3PTY call of two calls on hold"}, + { ACTION_POTS_TRANSFER, + "pots-transfer", &EndpointAppPBX::action_init_pots_transfer, NULL, NULL, + 0, + "When using POTS: Interconnect two calls on hold"}, { -1, NULL, NULL, NULL, NULL, 0, NULL} }; @@ -980,7 +1018,7 @@ struct route_ruleset *ruleset_parse(void) while(*p!=':' && *p!='\0') { /* read item text */ i = 0; - while((*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9')) { + while((*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9') || *p == '-') { if (*p>='A' && *p<='Z') *p = *p-'A'+'a'; /* lower case */ key[i++] = *p++; if (i == sizeof(key)) i--; /* limit */ @@ -1213,19 +1251,25 @@ struct route_ruleset *ruleset_parse(void) /* parse service value */ case COND_TYPE_CAPABILITY: - if (!strncasecmp("speech", p, 6)) + if (!strncasecmp("speech", p, 6)) { cond->integer_value = INFO_BC_SPEECH; - else if (!strncasecmp("audio", p, 5)) + p += 6; + } else if (!strncasecmp("audio", p, 5)) { cond->integer_value = INFO_BC_AUDIO; - else if (!strncasecmp("video", p, 5)) + p += 5; + } else if (!strncasecmp("video", p, 5)) { cond->integer_value = INFO_BC_VIDEO; - else if (!strncasecmp("digital-restricted", p, 18)) + p += 5; + } else if (!strncasecmp("digital-restricted", p, 18)) { cond->integer_value = INFO_BC_DATARESTRICTED; - else if (!strncasecmp("digital-unrestricted", p, 20)) + p += 18; + } else if (!strncasecmp("digital-unrestricted", p, 20)) { cond->integer_value = INFO_BC_DATAUNRESTRICTED; - else if (!strncasecmp("digital-unrestricted-tones", p, 26)) + p += 20; + } else if (!strncasecmp("digital-unrestricted-tones", p, 26)) { cond->integer_value = INFO_BC_DATAUNRESTRICTED_TONES; - else { + p += 26; + } else { SPRINT(failure, "Given service type is invalid or misspelled."); goto parse_error; } @@ -1234,17 +1278,70 @@ struct route_ruleset *ruleset_parse(void) /* parse bmode value */ case COND_TYPE_BMODE: - if (!strncasecmp("transparent", p, 11)) + if (!strncasecmp("transparent", p, 11)) { cond->integer_value = INFO_BMODE_CIRCUIT; - else if (!strncasecmp("hdlc", p, 4)) + p += 11; + } else if (!strncasecmp("hdlc", p, 4)) { cond->integer_value = INFO_BMODE_PACKET; - else { + p += 4; + } else { SPRINT(failure, "Given bchannel mode is invalid or misspelled."); goto parse_error; } 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; + p += 9; + } else if (!strncasecmp("faxg2g3", p, 7)) { + cond->integer_value = INFO_HLC_FAXG2G3; + p += 7; + } else if (!strncasecmp("faxg4", p, 5)) { + cond->integer_value = INFO_HLC_FAXG4; + p += 5; + } else if (!strncasecmp("teletex1", p, 8)) { + cond->integer_value = INFO_HLC_TELETEX1; + p += 8; + } else if (!strncasecmp("teletex2", p, 8)) { + cond->integer_value = INFO_HLC_TELETEX2; + p += 8; + } else if (!strncasecmp("teletex3", p, 8)) { + cond->integer_value = INFO_HLC_TELETEX3; + p += 8; + } else if (!strncasecmp("videotex1", p, 9)) { + cond->integer_value = INFO_HLC_VIDEOTEX1; + p += 9; + } else if (!strncasecmp("videotex2", p, 9)) { + cond->integer_value = INFO_HLC_VIDEOTEX2; + p += 9; + } else if (!strncasecmp("telex", p, 5)) { + cond->integer_value = INFO_HLC_TELEX; + p += 5; + } else if (!strncasecmp("mhs", p, 3)) { + cond->integer_value = INFO_HLC_MHS; + p += 3; + } else if (!strncasecmp("osi", p, 3)) { + cond->integer_value = INFO_HLC_OSI; + p += 3; + } else if (!strncasecmp("maintenance", p, 11)) { + cond->integer_value = INFO_HLC_MAINTENANCE; + p += 11; + } else if (!strncasecmp("management", p, 10)) { + cond->integer_value = INFO_HLC_MANAGEMENT; + p += 10; + } else if (!strncasecmp("audiovisual", p, 11)) { + cond->integer_value = INFO_HLC_AUDIOVISUAL; + p += 11; + } 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'; @@ -1365,11 +1462,15 @@ struct route_ruleset *ruleset_parse(void) while(*p != 0) { /* read param text */ i = 0; - while((*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9')) { + while((*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9') || *p == '-') { if (*p>='A' && *p<='Z') *p = *p-'A'+'a'; /* lower case */ key[i++] = *p++; if (i == sizeof(key)) i--; /* limit */ } + if (*p == ':') { + p++; + goto nextaction; + } key[i] = 0; if (key[0] == '\0') { SPRINT(failure, "Expecting parameter name."); @@ -1529,6 +1630,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 +1722,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")) { @@ -1776,24 +1939,36 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) istrue, couldbetrue, condition, - dialing_required, - avail, - any; + dialing_required; struct route_rule *rule = ruleset->rule_first; struct route_cond *cond; struct route_action *action = NULL; unsigned long comp_len; - int j, jj; + int j; + 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; +#ifdef WITH_MISDN struct mISDNport *mISDNport; + int avail, + any; + int jj; + class Port *port; + class Pfxs *ourfxs, *fxs; + int fxs_count; + int fxs_age; +#endif struct admin_list *admin; + time_t now; + struct tm *now_tm; + int pid, status; /* 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)); @@ -1824,17 +1999,20 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) break; case MATCH_PORT: +#ifdef WITH_MISDN if (ea_endpoint->ep_portlist) if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_MASK) != PORT_CLASS_mISDN) break; integer = e_callerinfo.isdn_port; goto match_integer; +#endif + break; case MATCH_INTERFACE: if (!e_callerinfo.interface[0]) break; string = e_callerinfo.interface; - goto match_string_prefix; + goto match_string; case MATCH_CALLERID: string = callerid; @@ -1845,7 +2023,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 +2085,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 +2138,33 @@ 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 */ + switch ((pid = fork())) { + case 0: + execve(cond->string_value, argv, environ); + perror("execve"); + exit(1); + case -1: + break; + default: + waitpid(pid, &status, 0); + if (0 == WEXITSTATUS(status)) + istrue = 1; + } break; case MATCH_DEFAULT: @@ -1960,12 +2173,17 @@ 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; case MATCH_FREE: case MATCH_NOTFREE: +#ifdef WITH_MISDN if (!(comp_len = (unsigned long)strchr(cond->string_value, ':'))) break; comp_len = comp_len-(unsigned long)cond->string_value; @@ -1994,10 +2212,12 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) if (avail < atoi(cond->string_value + comp_len + 1)) istrue = 1; } +#endif break; case MATCH_DOWN: +#ifdef WITH_MISDN mISDNport = mISDNport_first; while(mISDNport) { if (mISDNport->ifport) @@ -2008,9 +2228,11 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) } if (!mISDNport) /* all down */ istrue = 1; +#endif break; case MATCH_UP: +#ifdef WITH_MISDN mISDNport = mISDNport_first; while(mISDNport) { if (mISDNport->ifport) @@ -2022,10 +2244,12 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) } if (mISDNport) /* one link at least */ istrue = 1; +#endif break; case MATCH_BUSY: case MATCH_IDLE: +#ifdef WITH_MISDN any = 0; mISDNport = mISDNport_first; while(mISDNport) { @@ -2039,6 +2263,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) istrue = 1; if (!mISDNport && cond->match==MATCH_IDLE) istrue = 1; +#endif break; case MATCH_REMOTE: @@ -2055,6 +2280,86 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) istrue = 1; break; +#ifdef WITH_MISDN + case MATCH_POTS_FLASH: + if (e_dialinginfo.flash) + istrue = 1; + break; + + case MATCH_POTS_CW: + port = find_port_id(ea_endpoint->ep_portlist->port_id); + if (!port) + break; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) + break; + ourfxs = (class Pfxs *)port; + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + if (fxs->p_state == PORT_STATE_OUT_ALERTING) { + istrue = 1; + break; + } + } + } + port = port->next; + } + break; + + case MATCH_POTS_CALLS: + port = find_port_id(ea_endpoint->ep_portlist->port_id); + if (!port) + break; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) + break; + ourfxs = (class Pfxs *)port; + integer = 0; + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + if (fxs->p_state == PORT_STATE_CONNECT) { + integer++; + } + } + } + port = port->next; + } + goto match_integer; + + case MATCH_POTS_LAST: + port = find_port_id(ea_endpoint->ep_portlist->port_id); + if (!port) + break; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) + break; + ourfxs = (class Pfxs *)port; + /* integer gets the call number that has been the least active call on hold */ + fxs_age = -1; + fxs_count = 0; + integer = 0; + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + if (fxs->p_state == PORT_STATE_CONNECT) { + fxs_count++; + if (fxs->p_m_fxs_age > fxs_age) { + fxs_age = fxs->p_m_fxs_age; + integer = fxs_count; + } + } + } + } + port = port->next; + } + goto match_integer; +#endif + default: PERROR("Software error: MATCH_* %d not parsed in function '%s'", cond->match, __FUNCTION__); break; @@ -2163,18 +2468,19 @@ 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 || timeoutaction_first; - e_match_to_extdialing = e_dialinginfo.id + dialing_required; + if (timeout>now_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 */ + 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 */ } 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 +2491,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-now_ll) / 1000000, (match_timeout-now_ll) % 1000000); + } return(action); } @@ -2239,14 +2550,6 @@ struct route_action action_internal = { 0, }; -struct route_action action_remote = { - NULL, - NULL, - ACTION_REMOTE, - 0, - 0, -}; - struct route_action action_vbox = { NULL, NULL,