![]() |
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.
-------------------------------------------------- BadPageHandlingMethod
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