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] receiving: logic of RTN negative followed by MPS
Giulio Orsero wrote:
On 4/26/06, Giulio Orsero <giulioo@xxxxxxxxx> wrote:
On 4/25/06, Lee Howard <faxguy@xxxxxxxxxxxxxxxx> wrote:
> Try the attached patch. It causes the DCN signal to be sent instead of
> RTN, and that should cause the sender to hang up or send DCN in reply,
> and the received but poor-quality page will get saved by virtue of
> SaveUnconfirmedPages... I hope.
The patch worked as intended.
So with this patch the sender knew something was wrong and could do
something about it, both sender and receiver happy.
Attached is a patch that I'm now committing to the repository at
hylafax.sourceforge.net. It will be in the 4.3.0.3 subrelease there. It
adds a feature called "BadPageHandlingMethod". I've included the man
page documentation below.
To accomplish the setting you desired here you would do:
BadPageHandlingMethod: DCN
My recommended setting would generally be the default, which is:
BadPageHandlingMethod: RTN-SAVE
I've not made this work in Class 2 because I'm too lazy to do that
part... the Class 2 code isn't as easy to manipulate here, it doesn't
seem... since it may be difficult to control the modem's behavior as
desired... especially when it performs copy-quality checking/correction.
Thanks,
Lee.
--------------------------------------------------
BadPageHandlingMethod
(Class 1/1.0 only) Specifies how to react to a bad page received from
the remote sender: one of ‘‘RTN’’, ‘‘DCN’’, or ‘‘RTN-SAVE’’.
If a page is received in non-ECM mode with unacceptable quality
according to PercentGoodLines or MaxConseutiveBadLines then it can be
somewhat difficult to inform the sender of the problem. Historically,
HylaFAX has assumed that signalling RTN to the sender will accomplish
this. However, some senders are incapable of retransmitting pages, and
to reduce burden they treat an RTN signal as a receipt confirmation and
proceed to the next page without notifying the sending user of the
potential problem in readability on the receive-end. (The assumption
there being that the receiving user will notify the sending user if
there actually is a redability problem.)
A setting of ‘‘RTN’’ is the historic behavior and assumes that an RTN
signal will be enough to get the sender to retransmit or be otherwise
informed of a potential readability problem on the receive-end. The
previously-received page data is marked to be overwritten by the next
page data received from the sender.
A setting of ‘‘DCN’’ tells HylaFAX to transmit a DCN signal in response
to the post-page message and should trigger a call abortion by the
sender. This should clearly indicate a problem in page readability to
the sender, although the receipt of any following pages in a later call
cannot be guaranteed.
A setting of ‘‘RTN-SAVE’’ more closely approximates the behavior of
other fax receivers (especially fax machines). It causes HylaFAX to send
the RTN signal but it saves the previously received page data and places
the next transmitted page data in another page. This is the default
setting. However, this could result in multiple copies of the same page
image being saved in the same file - if the sender does indeed
retransmit the unacceptable pages during the same call.
diff -Nru hylafax.orig/faxd/Class1.h hylafax/faxd/Class1.h
--- hylafax.orig/faxd/Class1.h 2006-05-02 15:54:08.000000000 -0700
+++ hylafax/faxd/Class1.h 2006-05-03 17:57:46.000000000 -0700
@@ -139,7 +139,7 @@
u_int f3, const fxStr& nsf,
u_int f4, const fxStr& id,
u_int f5, FaxParams& dics,
- u_int timer, fxStr& emsg);
+ u_int timer, bool notransmit, fxStr& emsg);
bool recvDCSFrames(HDLCFrame& frame);
bool recvTraining();
bool recvPPM(int& ppm, fxStr& emsg);
diff -Nru hylafax.orig/faxd/Class1Poll.c++ hylafax/faxd/Class1Poll.c++
--- hylafax.orig/faxd/Class1Poll.c++ 2006-05-02 15:54:08.000000000 -0700
+++ hylafax/faxd/Class1Poll.c++ 2006-05-03 18:04:19.000000000 -0700
@@ -66,5 +66,5 @@
0, fxStr::null,
FCF_CIG, cig,
FCF_DTC, dtc,
- conf.t1Timer, emsg);
+ conf.t1Timer, false, emsg);
}
diff -Nru hylafax.orig/faxd/Class1Recv.c++ hylafax/faxd/Class1Recv.c++
--- hylafax.orig/faxd/Class1Recv.c++ 2006-05-02 15:54:08.000000000 -0700
+++ hylafax/faxd/Class1Recv.c++ 2006-05-04 15:41:04.521958792 -0700
@@ -107,7 +107,7 @@
FCF_NSF|FCF_RCVR, nsf,
FCF_CSI|FCF_RCVR, lid,
FCF_DIS|FCF_RCVR, dis,
- conf.class1RecvIdentTimer, emsg);
+ conf.class1RecvIdentTimer, false, emsg);
}
/*
@@ -138,38 +138,40 @@
u_int f3, const fxStr& nsf,
u_int f4, const fxStr& id,
u_int f5, FaxParams& dics,
- u_int timer, fxStr& emsg)
+ u_int timer, bool notransmit, fxStr& emsg)
{
u_int t1 = howmany(timer, 1000); // in seconds
u_int trecovery = howmany(conf.class1TrainingRecovery, 1000);
time_t start = Sys::now();
HDLCFrame frame(conf.class1FrameOverhead);
- bool framesSent;
+ bool framesSent = false;
emsg = "No answer (T.30 T1 timeout)";
- /*
- * Transmit (PWD) (SUB) (CSI) DIS frames when the receiving
- * station or (PWD) (SEP) (CIG) DTC when initiating a poll.
- */
- if (f1) {
- startTimeout(7550);
- framesSent = sendFrame(f1, pwd, false);
- stopTimeout("sending PWD frame");
- } else if (f2) {
- startTimeout(7550);
- framesSent = sendFrame(f2, addr, false);
- stopTimeout("sending SUB/SEP frame");
- } else if (f3) {
- startTimeout(7550);
- framesSent = sendFrame(f3, (const u_char*)HYLAFAX_NSF, nsf, false);
- stopTimeout("sending NSF frame");
- } else {
- startTimeout(7550);
- framesSent = sendFrame(f4, id, false);
- stopTimeout("sending CSI/CIG frame");
+ if (!notransmit) {
+ /*
+ * Transmit (PWD) (SUB) (CSI) DIS frames when the receiving
+ * station or (PWD) (SEP) (CIG) DTC when initiating a poll.
+ */
+ if (f1) {
+ startTimeout(7550);
+ framesSent = sendFrame(f1, pwd, false);
+ stopTimeout("sending PWD frame");
+ } else if (f2) {
+ startTimeout(7550);
+ framesSent = sendFrame(f2, addr, false);
+ stopTimeout("sending SUB/SEP frame");
+ } else if (f3) {
+ startTimeout(7550);
+ framesSent = sendFrame(f3, (const u_char*)HYLAFAX_NSF, nsf, false);
+ stopTimeout("sending NSF frame");
+ } else {
+ startTimeout(7550);
+ framesSent = sendFrame(f4, id, false);
+ stopTimeout("sending CSI/CIG frame");
+ }
}
for (;;) {
- if (framesSent) {
+ if (framesSent && !notransmit) {
if (f1) {
startTimeout(7550);
framesSent = sendFrame(f2, addr, false);
@@ -191,7 +193,7 @@
stopTimeout("sending DIS/DCS frame");
}
}
- if (framesSent) {
+ if (framesSent || notransmit) {
/*
* Wait for a response to be received. We wait T2
* rather than T4 due to empirical evidence for that need.
@@ -259,17 +261,19 @@
* be in the process of sending training.
*/
pause(conf.class1TrainingRecovery);
- /*
- * Retransmit ident frames.
- */
- if (f1)
- framesSent = transmitFrame(f1, pwd, false);
- else if (f2)
- framesSent = transmitFrame(f2, addr, false);
- else if (f3)
- framesSent = transmitFrame(f3, (const u_char*)HYLAFAX_NSF, nsf, false);
- else
- framesSent = transmitFrame(f4, id, false);
+ if (!notransmit) {
+ /*
+ * Retransmit ident frames.
+ */
+ if (f1)
+ framesSent = transmitFrame(f1, pwd, false);
+ else if (f2)
+ framesSent = transmitFrame(f2, addr, false);
+ else if (f3)
+ framesSent = transmitFrame(f3, (const u_char*)HYLAFAX_NSF, nsf, false);
+ else
+ framesSent = transmitFrame(f4, id, false);
+ }
}
return (false);
}
@@ -469,15 +473,27 @@
bool
Class1Modem::recvPage(TIFF* tif, u_int& ppm, fxStr& emsg, const fxStr& id)
{
- if (lastPPM == FCF_MPS && prevPage && pageGood) {
+ if (lastPPM == FCF_MPS && prevPage) {
/*
* Resume sending HDLC frame (send data)
* The carrier is already raised. Thus we
* use sendFrame() instead of transmitFrame().
*/
- startTimeout(7550);
- (void) sendFrame((sendERR ? FCF_ERR : FCF_MCF)|FCF_RCVR);
- stopTimeout("sending HDLC frame");
+ if (pageGood) {
+ startTimeout(7550);
+ (void) sendFrame((sendERR ? FCF_ERR : FCF_MCF)|FCF_RCVR);
+ stopTimeout("sending HDLC frame");
+ } else if (conf.badPageHandling == FaxModem::BADPAGE_RTNSAVE) {
+ startTimeout(7550);
+ (void) sendFrame(FCF_RTN|FCF_RCVR);
+ stopTimeout("sending HDLC frame");
+ FaxParams dis = modemDIS();
+ if (!recvIdentification(0, fxStr::null, 0, fxStr::null,
+ 0, fxStr::null, 0, fxStr::null, 0, dis,
+ conf.class1RecvIdentTimer, true, emsg)) {
+ return (false);
+ }
+ }
}
time_t t2end = 0;
@@ -697,13 +713,15 @@
pageGood = false;
if (params.ec != EC_DISABLE) return (false);
}
- if (!pageGood) recvResetPage(tif);
+ if (!pageGood && conf.badPageHandling == FaxModem::BADPAGE_RTN)
+ recvResetPage(tif);
if (signalRcvd == 0) tracePPM("RECV recv", lastPPM);
/*
* [Re]transmit post page response.
*/
- if (pageGood) {
+ if (pageGood || conf.badPageHandling == FaxModem::BADPAGE_RTNSAVE) {
+ if (!pageGood) lastPPM = FCF_MPS; // FaxModem::BADPAGE_RTNSAVE
/*
* If post page message confirms the page
* that we just received, write it to disk.
@@ -801,7 +819,10 @@
} else {
(void) transmitFrame((sendERR ? FCF_ERR : FCF_MCF)|FCF_RCVR);
}
- tracePPR("RECV send", sendERR ? FCF_ERR : FCF_MCF);
+ if (pageGood)
+ tracePPR("RECV send", sendERR ? FCF_ERR : FCF_MCF);
+ else
+ tracePPR("RECV send", FCF_RTN);
}
/*
* Reset state so that the next call looks
@@ -835,8 +856,9 @@
emsg = "Failure to receive silence.";
return (false);
}
- (void) transmitFrame(FCF_RTN|FCF_RCVR);
- tracePPR("RECV send", FCF_RTN);
+ u_int rtnfcf = conf.badPageHandling == FaxModem::BADPAGE_DCN ? FCF_DCN : FCF_RTN;
+ (void) transmitFrame(rtnfcf|FCF_RCVR);
+ tracePPR("RECV send", rtnfcf);
/*
* Reset the TIFF-related state so that subsequent
* writes will overwrite the previous data.
diff -Nru hylafax.orig/faxd/FaxModem.h hylafax/faxd/FaxModem.h
--- hylafax.orig/faxd/FaxModem.h 2006-05-02 15:54:08.000000000 -0700
+++ hylafax/faxd/FaxModem.h 2006-05-02 17:07:25.000000000 -0700
@@ -44,6 +44,7 @@
// NB: these would be enums in the FaxModem class
// if there were a portable way to refer to them!
typedef unsigned int RTNHandling; // RTN signal handling method
+typedef unsigned int BadPageHandling; // bad page (received) handling method
typedef unsigned int JBIGSupport; // JBIG support available
/*
@@ -176,6 +177,11 @@
RTN_IGNORE = 2, // ignore error and send next page
RTN_RETRANSMITIGNORE = 3 // retransmit but ignore error instead of hanging up
};
+ enum { // FaxModem::BadPageHandling
+ BADPAGE_RTN = 0, // send RTN, expect a retransmission
+ BADPAGE_DCN = 1, // send DCN, expect a disconnection
+ BADPAGE_RTNSAVE = 2 // send RTN, but save the page
+ };
enum { // FaxModem::JBIGSupport
JBIG_NONE = 0, // no JBIG support
JBIG_RECV = 1, // receive-only JBIG support
diff -Nru hylafax.orig/faxd/ModemConfig.c++ hylafax/faxd/ModemConfig.c++
--- hylafax.orig/faxd/ModemConfig.c++ 2006-05-02 15:54:08.000000000 -0700
+++ hylafax/faxd/ModemConfig.c++ 2006-05-02 17:03:06.000000000 -0700
@@ -265,6 +265,7 @@
setVolumeCmds("ATM0 ATL0M1 ATL1M1 ATL2M1 ATL3M1");
recvDataFormat = DF_ALL; // default to no transcoding
rtnHandling = FaxModem::RTN_RETRANSMITIGNORE; // retransmit until MCF/MPS
+ badPageHandling = FaxModem::BADPAGE_RTNSAVE; // send RTN but save the page
saveUnconfirmedPages = true; // keep unconfirmed pages
softRTFCC = true; // real-time fax comp. conv. (software)
noAnswerVoice = false; // answer voice calls
@@ -575,6 +576,20 @@
}
u_int
+ModemConfig::getBadPageHandling(const char* cp)
+{
+ BadPageHandling bph;
+ if (valeq(cp, "RTN")) {
+ bph = FaxModem::BADPAGE_RTN;
+ } else if (valeq(cp, "DCN")) {
+ bph = FaxModem::BADPAGE_DCN;
+ } else {
+ bph = FaxModem::BADPAGE_RTNSAVE;
+ }
+ return (bph);
+}
+
+u_int
ModemConfig::getJBIGSupport(const char* cp)
{
JBIGSupport js;
@@ -725,6 +740,8 @@
recvDataFormat = getDataFormat(value);
else if (streq(tag, "rtnhandlingmethod"))
rtnHandling = getRTNHandling(value);
+ else if (streq(tag, "badpagehandlingmethod"))
+ badPageHandling = getBadPageHandling(value);
else if (streq(tag, "class2ecmtype"))
class2ECMType = getECMType(value);
else if (streq(tag, "class2usehex"))
diff -Nru hylafax.orig/faxd/ModemConfig.h hylafax/faxd/ModemConfig.h
--- hylafax.orig/faxd/ModemConfig.h 2006-05-02 15:54:08.000000000 -0700
+++ hylafax/faxd/ModemConfig.h 2006-05-02 17:10:01.000000000 -0700
@@ -57,6 +57,7 @@
u_int getSpeed(const char* value);
u_int getDataFormat(const char* value);
u_int getRTNHandling(const char* cp);
+ u_int getBadPageHandling(const char* cp);
u_int getJBIGSupport(const char* cp);
ECMType getECMType(const char* cp);
@@ -228,6 +229,7 @@
u_int recvDataFormat; // received facsimile data format
RTNHandling rtnHandling; // RTN signal handling method
+ BadPageHandling badPageHandling; // bad page (received) handling method
JBIGSupport class1JBIGSupport; // monochrome JBIG support
bool saveUnconfirmedPages; // don't delete unconfirmed pages
diff -Nru hylafax.orig/man/hylafax-config.4f hylafax/man/hylafax-config.4f
--- hylafax.orig/man/hylafax-config.4f 2006-05-02 15:54:08.000000000 -0700
+++ hylafax/man/hylafax-config.4f 2006-05-04 15:38:39.889946200 -0700
@@ -120,6 +120,7 @@
AnswerRotary string \s-1Any\s+1 alternatives for answering calls
AnswerBias integer \- bias to apply to successful rotary answer
AreaCode\(S2 string \- local area code
+BadPageHandlingMethod string \s-1RTN-SAVE\s+1 bad page received handling method
BatchLogs\(S1 boolean \s-1Yes\s+1 keep all session logs of a batch in a single log
CallIDAnswerLength integer \- answer call when CallIDPattern received
CallIDPattern strint \- call identification pattern string
@@ -507,6 +508,44 @@
.B DialStringRules
below.)
.TP
+.B BadPageHandlingMethod
+(Class 1/1.0 only) Specifies how to react to a bad page received from the remote sender:
+one of ``\s-1RTN\s+1'', ``\s-1DCN\s+1'', or ``\s-1RTN-SAVE\s+1''.
+
+If a page is received in non-ECM mode with unacceptable quality
+according to
+.BR PercentGoodLines
+or
+.BR MaxConseutiveBadLines
+then it can be somewhat difficult to inform the sender of the problem.
+Historically, \*(Fx has assumed that signalling RTN to the sender will
+accomplish this. However, some senders are incapable of retransmitting
+pages, and to reduce burden they treat an RTN signal as a receipt
+confirmation and proceed to the next page without notifying the sending
+user of the potential problem in readability on the receive-end. (The
+assumption there being that the receiving user will notify the sending
+user if there actually is a redability problem.)
+
+A setting of ``\s-1RTN\s+1'' is the historic behavior and assumes that
+an RTN signal will be enough to get the sender to retransmit or be
+otherwise informed of a potential readability problem on the receive-end.
+The previously-received page data is marked to be overwritten by the next page
+data received from the sender.
+
+A setting of ``\s-1DCN\s+1'' tells \*(Fx to transmit a DCN signal in
+response to the post-page message and should trigger a call abortion by
+the sender. This should clearly indicate a problem in page readability
+to the sender, although the receipt of any following pages in a later
+call cannot be guaranteed.
+
+A setting of ``\s-1RTN-SAVE\s+1'' more closely approximates the behavior
+of other fax receivers (especially fax machines). It causes \*(Fx to
+send the RTN signal but it saves the previously received page data and places
+the next transmitted page data in another page. This is the default
+setting. However, this could result in multiple copies of the same page
+image being saved in the same file - if the sender does indeed retransmit
+the unacceptable pages during the same call.
+.TP
.B BatchLogs\(S1
When sending or recieving multiple documents (denoted by EOM), this
value determines if the session logs span the entire batch or, if set