HylaFAX The world's most advanced open source fax server

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [hylafax-users] multiport modem and user based grouping



* Lee Howard <faxguy@xxxxxxxxxxxxxxxx> [060112 11:38]:
 
> Attached is a patch that will give you this feature.  It should apply to 
> most recent versions of HylaFAX.  If you desire it in a tarball it is in 
> 4.2.5.1 which can be found at:
> 
>  http://hylafax.sourceforge.net/news/4.2.5.1.php
> 
> The feature basically adds an "owner" option to DestControls.  
> Documentation can be seen in 'man destctrls' and here:
> 
>  http://hylafax.sourceforge.net/man/destctrls.php
> 
> But, basically by adding an "owner" field to the DestControls entry you 
> will restrict the application of that entry to apply only to jobs 
> submitted by that owner (hfaxd login username).  So, for example 
> DestControls entries of:
> 
> .* owner=omer modem=ttyS0
> .* owner=lee modem=ttyS1
> 
> This would make all jobs submitted by "omer" be sent through modem ttyS0 
> and all jobs submitted by "lee" be sent through modem ttyS1.


I've attached the start of another approach to gaining this
functionality, but in a bit more generic.

The intention is to make a "jobcontrls", similar to destcontrols.

The idea is that you can control jobs (same as destcontrols) based on a
match of any (or no) job parameters.

This version currently only supports dest, owner, and client, but can
easily be extended to include almost any user-specifiable job parameter.
Any, or none of the 3 fields can be matched, and all are regex matches.

This patch slightly changes the format of the destcontrols file (with
the thought that this could grow into a jobcontrol file, or such,
possibly with a backwards compatible destcontrols parser ).  The file
format is:
	[dest=<dest regex>] [owner=<owner_regex>] [client=<client_regex>] action=...

So, basically, instead of just the single "destination regex", you can
specify regex for other input fields, somehting like:
	dest=911                        RejectNotice="No 911"
	owner=aidan client=ifax         RejectNotice=reject-aidan-remote
	owner=aidan client=localhost    RejectNotice=reject-aidan-LOCAL
	dest=+1215 client=localhost	Modem=localgroup

I have a few concerns with the format of this file.  I don't really like
the "overloading" of both input fields and output fields with the =
sign.  A possible format could be a white-space separated file:
	<dest_regex>	<owner_regex>	<client_regex>	<action1>	[ [<action2] ... ]
but this doesn't lead to a very extendable format, and makes adding (or
removing) fields problematic.

Thoughts, comments?
a.
-- 
Aidan Van Dyk                                             aidan@xxxxxxxx
Senior Software Developer                          +1 215 438-4638 x8103
iFAX Solutions, Inc.                                http://www.ifax.com/
===== faxd/DestControl.c++ 1.10 vs edited =====
--- 1.10/faxd/DestControl.c++	2004-04-21 12:30:45 -04:00
+++ edited/faxd/DestControl.c++	2006-03-14 14:08:15 -05:00
@@ -42,12 +42,41 @@
 #define	isDefined(b)		(defined & b)
 #define	setDefined(b)		(defined |= b)
 
+
+static bool IsREmatch (RE* p, const fxStr& m)
+{
+    if (p)
+	return p->Find(m);
+    return true;
+}
+
+static bool IsREerror (RE* p)
+{
+    if (p)
+	return p->getErrorCode() > REG_NOMATCH;
+    return false;
+}
+
 const DestControlInfo DestControlInfo::defControlInfo;
 
-DestControlInfo::DestControlInfo()		 : pattern("")	{ defined = 0; }
-DestControlInfo::DestControlInfo(const char* re) : pattern(re)	{ defined = 0; }
+DestControlInfo::DestControlInfo()		 
+{
+    defined = 0;
+}
+
+#ifdef AIDAN
+DestControlInfo::DestControlInfo(const char* d, const char* o)
+  : dest(d)
+  , owner(o)
+{
+    defined = 0;
+}
+#endif
+
 DestControlInfo::DestControlInfo(const DestControlInfo& other)
-    : pattern(other.pattern)
+    : dest(other.dest)
+    , owner(other.owner)
+    , client(other.client)
     , rejectNotice(other.rejectNotice)
     , modem(other.modem)
     , tod(other.tod)
@@ -71,7 +100,15 @@
 void
 DestControlInfo::parseEntry(const char* tag, const char* value, bool quoted)
 {
-    if (streq(tag, "rejectnotice")) {
+    if (streq(tag, "destination")) {
+       dest = new RE(value);
+    } else if (streq(tag, "dest")) {
+       dest = new RE(value);
+    } else if (streq(tag, "owner")) {
+       owner = new RE(value);
+    } else if (streq(tag, "client")) {
+       client = new RE(value);
+    } else if (streq(tag, "rejectnotice")) {
 	rejectNotice = value;
     } else if (streq(tag, "modem")) {
 	modem = value;
@@ -100,6 +137,7 @@
 	vres = getNumber(value);
 	setDefined(DCI_VRES);
     } else {
+        logError(" - appending as args");
 	if( args != "" )
 	    args.append('\0');
 	const char* quote = quoted ? "\"" : "";
@@ -203,7 +241,7 @@
 }
 
 const DestControlInfo&
-DestControl::operator[](const fxStr& canon)
+DestControl::find (const fxStr& f_dest, const fxStr& f_owner, const fxStr& f_client)
 {
     struct stat sb;
     if (Sys::stat(filename, sb) == 0 && sb.st_mtime > lastModTime) {
@@ -213,7 +251,9 @@
     }
     for (u_int i = 0, n = info.length(); i < n; i++) {
 	DestControlInfo& dci = info[i];
-	if (dci.pattern.Find(canon))
+	if (IsREmatch(dci.dest, f_dest)
+		    && IsREmatch(dci.owner, f_owner)
+		    && IsREmatch(dci.client, f_client) )
 	    return (dci);
     }
     return (DestControlInfo::defControlInfo);
@@ -269,26 +309,8 @@
     for (;;) {
 	if (!readLine(fp, line, sizeof (line)-1))
 	    return (false);
-	char* cp;
-	for (cp = line; *cp && !isspace(*cp); cp++)
-	    ;
-	if (*cp == '\0')
-	    continue;
-	if (cp == line) {
-	    parseError("Missing regular expression.");
-	    skipEntry(fp, line, sizeof (line)-1);
-	    return (true);
-	}
-	*cp++ = '\0';
-	DestControlInfo dci(line);
-	if (dci.pattern.getErrorCode() > REG_NOMATCH) {
-	    RE& re = dci.pattern;
-	    fxStr emsg;
-	    re.getError(emsg);
-	    parseError("Bad regular expression: %s: " | emsg, re.pattern());
-	    skipEntry(fp, line, sizeof (line)-1);
-	    return (true);
-	}
+	DestControlInfo dci;
+	char* cp = line;
 	for (;;) {
 	    while (isspace(*cp))
 		cp++;
@@ -343,6 +365,30 @@
 		*cp++ = '\0';
 	    if (tag[0] != '\0')
 		dci.parseEntry(tag, value, quoted);
+	}
+	if (IsREerror(dci.dest) ) {
+	    RE& re = *dci.dest;
+	    fxStr emsg;
+	    re.getError(emsg);
+	    parseError("Bad destination regular expression: %s: " | emsg, re.pattern());
+	    skipEntry(fp, line, sizeof (line)-1);
+	    return (true);
+	}
+	if (IsREerror(dci.owner) ) {
+	    RE& re = *dci.owner;
+	    fxStr emsg;
+	    re.getError(emsg);
+	    parseError("Bad owner regular expression: %s: " | emsg, re.pattern());
+	    skipEntry(fp, line, sizeof (line)-1);
+	    return (true);
+	}
+	if (IsREerror(dci.client) ) {
+	    RE& re = *dci.client;
+	    fxStr emsg;
+	    re.getError(emsg);
+	    parseError("Bad client regular expression: %s: " | emsg, re.pattern());
+	    skipEntry(fp, line, sizeof (line)-1);
+	    return (true);
 	}
     }
 }
===== faxd/DestControl.h 1.7 vs edited =====
--- 1.7/faxd/DestControl.h	2004-04-21 12:30:45 -04:00
+++ edited/faxd/DestControl.h	2006-03-14 14:08:34 -05:00
@@ -40,7 +40,12 @@
  */
 class DestControlInfo {
 private:
-    RE	pattern;		// destination pattern
+    /* Match fields */
+    REPtr	dest;			// destination pattern
+    REPtr	owner;			// owner pattern
+    REPtr	client;			// client pattern
+
+    /* Control fields */
     u_long	defined;		// parameters that were defined
     u_int	maxConcurrentCalls;	// max number of parallel calls
     u_int	maxSendPages;		// max pages in a send job
@@ -58,11 +63,14 @@
 
     friend class DestControl;
 public:
-    DestControlInfo(const char* regex);
+#ifdef AIDAN
+    DestControlInfo(const char* dest = "", const char* owner = "");
+#endif
     DestControlInfo();
     DestControlInfo(const DestControlInfo& other);
     ~DestControlInfo();
 
+
     int compare(const DestControlInfo*) const;
     void parseEntry(const char* tag, const char* value, bool quoted);
 
@@ -102,6 +110,7 @@
 
     void setFilename(const char* filename);
 
-    const DestControlInfo& operator[](const fxStr&);
+//    const DestControlInfo& operator[](const fxStr&);
+    const DestControlInfo& find (const fxStr& canon, const fxStr& owner, const fxStr& client);
 };
 #endif /* _DestControl_ */
===== faxd/faxQueueApp.c++ 1.70 vs edited =====
--- 1.70/faxd/faxQueueApp.c++	2005-10-27 17:53:07 -04:00
+++ edited/faxd/faxQueueApp.c++	2006-03-14 14:09:02 -05:00
@@ -232,6 +232,11 @@
     closedir(dir);
 }
 
+const DestControlInfo&
+faxQueueApp::getDCI(const Job& j, const FaxRequest*r)
+{
+	return destCtrls.find(j.dest, r->owner, r->client);
+}
 /*
  * Process a job.  Prepare it for transmission and
  * pass it on to the thread that does the actual
@@ -442,8 +447,8 @@
 		    setDead(job);
 		}
 	    }
-	    if (processnext) processJob(*targetjob, targetjob->breq, destJobs[targetjob->dest], destCtrls[targetjob->dest]);
-	    else if (startsendjob) sendJobStart(*targetjob->bfirst(), targetjob->bfirst()->breq, destCtrls[targetjob->dest]);
+	    if (processnext) processJob(*targetjob, targetjob->breq, destJobs[targetjob->dest], getDCI(*targetjob, targetjob->breq));
+	    else if (startsendjob) sendJobStart(*targetjob->bfirst(), targetjob->bfirst()->breq, getDCI(*targetjob, targetjob->breq));
 	    else {
 		/*
 		 * This destination was marked as called, but all jobs to this
@@ -2188,17 +2193,20 @@
      * ready for processing.
      */
     Job* jb;
-    const DestControlInfo& dci = destCtrls[job.dest];
     u_int n = 1;
-    while (isOKToCall(di, dci, n) && (jb = di.nextBlocked())) {
-	setReadyToRun(*jb);
-	if (!di.supportsBatching()) n++;
+    while (jb = di.nextBlocked()) {
 	FaxRequest* req = readRequest(*jb);
-	if (req) {
+	if (! req)
+	    continue;
+	const DestControlInfo& dci = getDCI(job, req);
+	if (isOKToCall(di, dci, n) )
+	{
+	    setReadyToRun(*jb);
+	    if (!di.supportsBatching()) n++;
 	    req->notice = "";
 	    updateRequest(*req, *jb);
-	    delete req;
 	}
+	delete req;
     }
 }
 
@@ -2291,7 +2299,7 @@
 		 * Do per-destination processing and checking.
 		 */
 		DestInfo& di = destJobs[job.dest];
-		const DestControlInfo& dci = destCtrls[job.dest];
+		const DestControlInfo& dci = getDCI(job, req);
 		/*
 		 * Constrain the maximum number of times the phone
 		 * will be dialed and/or the number of attempts that
===== faxd/faxQueueApp.h 1.20 vs edited =====
--- 1.20/faxd/faxQueueApp.h	2005-09-27 15:03:09 -04:00
+++ edited/faxd/faxQueueApp.h	2006-03-14 14:06:30 -05:00
@@ -174,6 +174,7 @@
     void	startTimeout(long ms);
     void	stopTimeout(const char* whichdir);
     const fxStr& pickCmd(const FaxRequest& req);
+    const DestControlInfo& getDCI(const Job& job, const FaxRequest* req);
 // FIFO-related stuff
     void	childStatus(pid_t, int);	// Dispatcher hook
     int		inputReady(int);		// Dispatcher hook

Attachment: signature.asc
Description: Digital signature




Project hosted by iFAX Solutions