"capability=speech|audio|video|digital-restricted|digital-unrestricted|digital-unrestricted-tones[,...]", "Matches the given bearer capability(s)."},
{ "infolayer1", MATCH_INFOLAYER1, COND_TYPE_INTEGER,
"infolayer1=<value>[,...]", "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=<value>[,...]", "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=<path>[,...]", "Mathes is the given file exists and if the first character is '1'."},
{ "execute", MATCH_EXECUTE, COND_TYPE_STRING,
"remote=<application name>","Matches if remote application is running."},
{ "notremote", MATCH_NOTREMOTE,COND_TYPE_STRING,
"notremote=<application name>","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=<total number>","When using POTS: Matches if given number of calls are held."},
+ { "pots-last", MATCH_POTS_LAST,COND_TYPE_INTEGER,
+ "pots-last=<call number>","When using POTS: Matches if given call number (1=oldest) was the last active call."},
{ NULL, 0, 0, NULL}
};
"infolayer1", PARAM_TYPE_INTEGER,
"infolayer1=<value>", "Alter the layer 1 information of a call. Use 3 for ALAW or 2 for uLAW."},
{ PARAM_HLC,
- "hlc", PARAM_TYPE_INTEGER,
- "hlc=<value>", "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=<value>", "Alter extended HLC value. (Mainenance only, don't use it.)"},
+ "exthlc", PARAM_TYPE_HLC,
+ "exthlc=<value>", "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."},
{ 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=<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_KEYPAD | 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,
"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_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,
"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,
// "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,
"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}
};
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 */
/* 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;
}
/* 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 <if>:<value> */
case COND_TYPE_IFATTR:
key[0] = key_to[0] = '\0';
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.");
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:
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")) {
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;
long long timeout, now_ll = 0, match_timeout = 0;
struct timeval current_time;
+#ifdef WITH_MISDN
struct mISDNport *mISDNport;
+ int avail;
+ 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_to_action = NULL;
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;
goto match_string_prefix;
case MATCH_EXTENSION:
- string = e_ext.name;
+ string = e_ext.number;
goto match_string;
case MATCH_DIALING:
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:
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;
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)
}
if (!mISDNport) /* all down */
istrue = 1;
+#endif
break;
case MATCH_UP:
+#ifdef WITH_MISDN
mISDNport = mISDNport_first;
while(mISDNport) {
if (mISDNport->ifport)
}
if (mISDNport) /* one link at least */
istrue = 1;
+#endif
break;
case MATCH_BUSY:
case MATCH_IDLE:
- any = 0;
+#ifdef WITH_MISDN
mISDNport = mISDNport_first;
while(mISDNport) {
if (mISDNport->ifport)
istrue = 1;
if (!mISDNport && cond->match==MATCH_IDLE)
istrue = 1;
+#endif
break;
case MATCH_REMOTE:
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;
cond = cond->next;
}
- 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;
+ 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) {
if (match_timeout == 0)
unsched_timer(&e_match_timeout); /* no timeout */
else {
- schedule_timer(&e_match_timeout, match_timeout / 1000000, match_timeout % 1000000);
+ schedule_timer(&e_match_timeout, (match_timeout-now_ll) / 1000000, (match_timeout-now_ll) % 1000000);
}
return(action);
}
0,
};
-struct route_action action_remote = {
- NULL,
- NULL,
- ACTION_REMOTE,
- 0,
- 0,
-};
-
struct route_action action_vbox = {
NULL,
NULL,