]> git.ipfire.org Git - thirdparty/HylaFAX.git/commitdiff
Bug 507: add CRP support to all recvFrame() calls
authorLee Howard <faxguy@howardsilvan.com>
Wed, 23 Mar 2005 15:37:55 +0000 (15:37 +0000)
committerLee Howard <faxguy@howardsilvan.com>
Wed, 23 Mar 2005 15:37:55 +0000 (15:37 +0000)
         fix some error-handling situations, timeouts, hangs, etc.

CHANGES
faxd/Class1.c++
faxd/Class1.h
faxd/Class1Recv.c++
faxd/Class1Send.c++
faxd/ModemServer.c++

diff --git a/CHANGES b/CHANGES
index d8d62745418f549039a7679a3c584d3669e62bf6..529a9d202b2181a9f4ed8821f709cd186211c2bd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,10 +2,11 @@
 
 Changelog for HylaFAX
 
+* improve some error-handling scenarios (23 Mar 2005)
 * improve identification of ECM blocks with zero frames (16 Mar 2005)
 * fix potential error in ECM reception frame counting (16 Mar 2005)
-* add CRP usage in receiving when message frames
-  are received corrupt (14 Mar 2005)
+* add CRP usage when message frames are received
+  corrupt (14,23 Mar 2005)
 * add Class1RMPersistence, better ECM +FCERROR handling (14 Mar 2005)
 * small fixes for compilation on AMD-64 (14 Mar 2005)
 * fix a few timeouts in faxgetty (11 Mar 2005)
index bcada3e56cd28c3463a9a618d148b55ca7cea2da..4c1216319600e74a16170f4f5be5cf1c34cbc32f 100644 (file)
@@ -703,6 +703,7 @@ Class1Modem::recvRawFrame(HDLCFrame& frame)
                    // wait for the control channel to reappear
                    // should we reset the timeout setting?
                    waitForDCEChannel(true);
+                   gotRTNC = true;
                    return (false);
                    break;
                default:
@@ -1285,21 +1286,21 @@ Class1Modem::transmitData(int br, u_char* data, u_int cc,
  * retransmit the frame. 
  */
 bool
-Class1Modem::recvFrame(HDLCFrame& frame, long ms, u_char docrp)
+Class1Modem::recvFrame(HDLCFrame& frame, u_char dir, long ms, bool readPending)
 {
     bool gotframe;
     u_short crpcnt = 0;
     if (useV34) {
        do {
-           if (crpcnt) tracePPR(docrp & FCF_SNDR ? "SEND send" : "RECV send", FCF_CRP);
+           if (crpcnt) tracePPR(dir == FCF_SNDR ? "SEND send" : "RECV send", FCF_CRP);
            frame.reset();
            gotframe = recvRawFrame(frame);
-       } while (docrp && crpcnt++ < 3 && !gotframe && !wasTimeout() && transmitFrame(docrp));
+       } while (!gotframe && !gotRTNC && !gotEOT && crpcnt++ < 3 && !wasTimeout() && transmitFrame(dir|FCF_CRP));
        return (gotframe);
     }
     startTimeout(ms);
-    bool readPending = atCmd(rhCmd, AT_NOTHING, 0);
-    if (readPending && waitFor(AT_CONNECT,0)){
+    if (!readPending) readPending = atCmd(rhCmd, AT_NOTHING, 0) && waitFor(AT_CONNECT, 0);
+    if (readPending{
         stopTimeout("waiting for HDLC flags");
         if (wasTimeout()){
             abortReceive();
@@ -1307,13 +1308,13 @@ Class1Modem::recvFrame(HDLCFrame& frame, long ms, u_char docrp)
         }
        do {
            if (crpcnt) {
-               tracePPR(docrp & FCF_SNDR ? "SEND send" : "RECV send", FCF_CRP);
+               tracePPR(dir == FCF_SNDR ? "SEND send" : "RECV send", FCF_CRP);
                if (!(atCmd(rhCmd, AT_NOTHING, 0) && waitFor(AT_CONNECT,0))) return (false);
            }
            frame.reset();
             gotframe = recvRawFrame(frame);
-       } while (docrp && crpcnt++ < 3 && !gotframe && !wasTimeout() &&
-               atCmd(conf.class1SwitchingCmd, AT_OK) && transmitFrame(docrp));
+       } while (!gotframe && crpcnt++ < 3 && !wasTimeout() &&
+               atCmd(conf.class1SwitchingCmd, AT_OK) && transmitFrame(dir|FCF_CRP));
        return (gotframe);
     }
     stopTimeout("waiting for v.21 carrier");
index 4f6d04c1dc9de244a7207f41e3c0fc63c0bc1de4..ad5f3f8182d8d264406c3a16f4218b2a83bdf5e5 100644 (file)
@@ -175,7 +175,7 @@ protected:
                    const u_char* bitrev, bool eod);
     bool       sendClass1ECMData(const u_char* data, u_int cc,
                     const u_char* bitrev, bool eod, u_int ppmcmd, fxStr& emsg);
-    bool       recvFrame(HDLCFrame& frame, long ms = 10*1000, u_char docrp = 0);
+    bool       recvFrame(HDLCFrame& frame, u_char dir, long ms = 10*1000, bool readPending = false);
     bool       recvTCF(int br, HDLCFrame&, const u_char* bitrev, long ms);
     bool       recvRawFrame(HDLCFrame& frame);
     bool       recvECMFrame(HDLCFrame& frame);
index 7b335747a608f507635361ef769ed14ebbd92e13..35132f1170ceb6ac3b4030e03376f95bc894251c 100644 (file)
@@ -195,7 +195,7 @@ Class1Modem::recvIdentification(
            /*
             * Wait for a response to be received.
             */
-           if (recvFrame(frame, conf.t4Timer)) {
+           if (recvFrame(frame, FCF_RCVR, conf.t4Timer)) {
                do {
                    /*
                     * Verify a DCS command response and, if
@@ -218,7 +218,7 @@ Class1Modem::recvIdentification(
                            return (true);
                        } else {
                            if (lastResponse == AT_FRH3 && waitFor(AT_CONNECT,0)) {
-                               gotframe = recvRawFrame(frame);
+                               gotframe = recvFrame(frame, FCF_RCVR, conf.t4Timer, true);
                                lastResponse == AT_NOTHING;
                            }
                        }
@@ -235,7 +235,7 @@ Class1Modem::recvIdentification(
                     * the full T1 timeout, as specified by the protocol.
                     */
                    t1 = howmany(conf.t1Timer, 1000);
-               } while (recvFrame(frame, conf.t2Timer));
+               } while (recvFrame(frame, FCF_RCVR, conf.t2Timer));
            }
            if (gotEOT) {
                emsg = "RSPREC error/got EOT";
@@ -293,7 +293,7 @@ Class1Modem::recvDCSFrames(HDLCFrame& frame)
            processDCSFrame(frame);
            break;
        }
-    } while (frame.moreFrames() && recvFrame(frame, conf.t4Timer));
+    } while (frame.moreFrames() && recvFrame(frame, FCF_RCVR, conf.t4Timer));
     return (frame.isOK() && frame.getFCF() == FCF_DCS);
 }
 
@@ -547,7 +547,7 @@ Class1Modem::recvPage(TIFF* tif, u_int& ppm, fxStr& emsg, const fxStr& id)
                } else {
                    if (rmResponse == AT_FRH3) {
                        HDLCFrame frame(conf.class1FrameOverhead);
-                       if (waitFor(AT_CONNECT,0) && recvRawFrame(frame))
+                       if (waitFor(AT_CONNECT,0) && recvFrame(frame, FCF_RCVR, conf.t4Timer, true))
                            signalRcvd = frame.getFCF();
                    }
                }
@@ -613,7 +613,7 @@ Class1Modem::recvPage(TIFF* tif, u_int& ppm, fxStr& emsg, const fxStr& id)
            ppmrcvd = true;
            lastPPM = signalRcvd;
        } else {
-           ppmrcvd = recvFrame(frame, timer, FCF_CRP|FCF_RCVR);
+           ppmrcvd = recvFrame(frame, FCF_RCVR, timer);
            if (ppmrcvd) lastPPM = frame.getFCF();
        }
        /*
@@ -641,7 +641,7 @@ Class1Modem::recvPage(TIFF* tif, u_int& ppm, fxStr& emsg, const fxStr& id)
                        if (!messageReceived) messageReceived = !(recvDCSFrames(frame));
                        if (!messageReceived) messageReceived = !(recvTraining());
                        if (messageReceived && lastResponse == AT_FRH3 && waitFor(AT_CONNECT,0)) {
-                           gotframe = recvRawFrame(frame);
+                           gotframe = recvFrame(frame, FCF_RCVR, conf.t4Timer, true);
                            lastResponse = AT_NOTHING;
                            messageReceived = false;
                        }
@@ -666,9 +666,8 @@ Class1Modem::recvPage(TIFF* tif, u_int& ppm, fxStr& emsg, const fxStr& id)
                     * that we just received, write it to disk.
                     */
                    if (messageReceived) {
-                       if (!useV34 && !atCmd(conf.class1SwitchingCmd, AT_OK)) {
+                       if (!useV34 && emsg == "" && !atCmd(conf.class1SwitchingCmd, AT_OK)) {
                            emsg = "Failure to receive silence.";
-                           return (false);
                        }
                        /*
                         * On servers where disk access may be bottlenecked or stressed,
@@ -709,7 +708,7 @@ Class1Modem::recvPage(TIFF* tif, u_int& ppm, fxStr& emsg, const fxStr& id)
                                                (void) transmitFrame(params.ec != EC_DISABLE ? FCF_RNR : FCF_CRP|FCF_RCVR);
                                                tracePPR("RECV send", params.ec != EC_DISABLE ? FCF_RNR : FCF_CRP);
                                                HDLCFrame rrframe(conf.class1FrameOverhead);
-                                               if (gotresponse = recvFrame(rrframe, conf.t4Timer, FCF_CRP|FCF_RCVR)) {
+                                               if (gotresponse = recvFrame(rrframe, FCF_RCVR, conf.t4Timer)) {
                                                    tracePPM("RECV recv", rrframe.getFCF());
                                                    if (params.ec != EC_DISABLE && rrframe.getFCF() != FCF_RR) {
                                                        protoTrace("Ignoring invalid response to RNR.");
@@ -813,9 +812,13 @@ Class1Modem::recvPage(TIFF* tif, u_int& ppm, fxStr& emsg, const fxStr& id)
            t2end = 0;
        } else {
            /*
-            * If remote is on hook, then modem responces [+FC]ERROR
-            * or NO CARRIER. I only try to prevent looping (V.F.)
+            * We didn't get a message.  Try to be resiliant by
+            * looking for the signal again, but prevent infinite
+            * looping with a timer.  However, if the modem is on
+            * hook, then modem responds ERROR or NO CARRIER, and
+            * for those cases there is no point in resiliancy.
             */
+           if (lastResponse == AT_NOCARRIER || lastResponse == AT_ERROR) break;
            if (t2end) {
                if (Sys::now() > t2end)
                    break;
@@ -949,9 +952,9 @@ Class1Modem::recvPageECMData(TIFF* tif, const Class2Params& params, fxStr& emsg)
                                    rtncframe.put(frameRev[ctrlFrameRcvd[i] & 0xFF]);
                                traceHDLCFrame("-->", rtncframe);
                            } else
-                               gotrtncframe = recvFrame(rtncframe, conf.t2Timer, FCF_CRP|FCF_RCVR);
+                               gotrtncframe = recvFrame(rtncframe, FCF_RCVR, conf.t2Timer);
                        } else {
-                           gotrtncframe = recvRawFrame(rtncframe);
+                           gotrtncframe = recvFrame(rtncframe, FCF_RCVR, conf.t2Timer, true);
                        }
                        if (gotrtncframe) {
                            switch (rtncframe.getFCF()) {
@@ -1240,8 +1243,8 @@ Class1Modem::recvPageECMData(TIFF* tif, const Class2Params& params, fxStr& emsg)
                HDLCFrame ppsframe(conf.class1FrameOverhead);
                u_short recvFrameCount = 0;
                do {
-                   gotpps = recvFrame(ppsframe, conf.t2Timer, FCF_CRP|FCF_RCVR);
-               } while (!gotpps && !wasTimeout() && ++recvFrameCount < 20);
+                   gotpps = recvFrame(ppsframe, FCF_RCVR, conf.t2Timer);
+               } while (!gotpps && !wasTimeout() && lastResponse != AT_NOCARRIER && ++recvFrameCount < 5);
                if (gotpps) {
                    tracePPM("RECV recv", ppsframe.getFCF());
                    if (ppsframe.getFCF() == FCF_PPS) {
@@ -1313,12 +1316,13 @@ Class1Modem::recvPageECMData(TIFF* tif, const Class2Params& params, fxStr& emsg)
                                        rtnframe = ppsframe;
                                    }
                                    pprcnt = 0;
-                                   if (signalRcvd != 0 || recvFrame(rtnframe, conf.t2Timer, FCF_CRP|FCF_RCVR)) {
+                                   if (signalRcvd != 0 || recvFrame(rtnframe, FCF_RCVR, conf.t2Timer)) {
                                        bool gotrtnframe = true;
                                        if (signalRcvd == 0) tracePPM("RECV recv", rtnframe.getFCF());
                                        else signalRcvd = 0;            // reset it, we're in-sync now
                                        recvFrameCount = 0;
-                                       while (rtnframe.getFCF() == FCF_PPS && recvFrameCount < 20 && gotrtnframe) {
+                                       lastResponse = AT_NOTHING;
+                                       while (rtnframe.getFCF() == FCF_PPS && lastResponse != AT_NOCARRIER && recvFrameCount < 5 && gotrtnframe) {
                                            // we sent PPR, but got PPS again...
                                            if (!useV34 && !atCmd(conf.class1SwitchingCmd, AT_OK)) {
                                                emsg = "Failure to receive silence.";
@@ -1332,7 +1336,7 @@ Class1Modem::recvPageECMData(TIFF* tif, const Class2Params& params, fxStr& emsg)
                                            }
                                            transmitFrame(FCF_PPR, fxStr(ppr, 32));
                                            tracePPR("RECV send", FCF_PPR);
-                                           gotrtnframe = recvFrame(rtnframe, conf.t2Timer, FCF_CRP|FCF_RCVR);
+                                           gotrtnframe = recvFrame(rtnframe, FCF_RCVR, conf.t2Timer);
                                            recvFrameCount++;
                                        }
                                        u_int dcs;                      // possible bits 1-16 of DCS in FIF
@@ -1532,7 +1536,7 @@ Class1Modem::recvPageECMData(TIFF* tif, const Class2Params& params, fxStr& emsg)
                                (void) transmitFrame(FCF_RNR|FCF_RCVR);
                                tracePPR("RECV send", FCF_RNR);
                                HDLCFrame rrframe(conf.class1FrameOverhead);
-                               if (gotresponse = recvFrame(rrframe, conf.t4Timer, FCF_CRP|FCF_RCVR)) {
+                               if (gotresponse = recvFrame(rrframe, FCF_RCVR, conf.t4Timer)) {
                                    tracePPM("RECV recv", rrframe.getFCF());
                                    if (params.ec != EC_DISABLE && rrframe.getFCF() != FCF_RR) {
                                        protoTrace("Ignoring invalid response to RNR.");
@@ -1626,7 +1630,7 @@ Class1Modem::recvEnd(fxStr&)
         */
        HDLCFrame frame(conf.class1FrameOverhead);
        do {
-           if (recvFrame(frame, conf.t2Timer)) {
+           if (recvFrame(frame, FCF_RCVR, conf.t2Timer)) {
                switch (frame.getFCF()) {
                case FCF_EOP:
                    (void) transmitFrame(FCF_MCF|FCF_RCVR);
index 9e6d0ace81507da76d6efde27745ef445ab45230..f14a23d8991557efd1357f6cfc715c0b0b5f0e64 100644 (file)
@@ -138,11 +138,11 @@ Class1Modem::getPrologue(Class2Params& params, bool& hasDoc, fxStr& emsg, u_int&
 
     bool framerecvd = false;
     if (batched & BATCH_FIRST)                 // receive carrier raised
-       framerecvd = recvRawFrame(frame);
+       framerecvd = recvFrame(frame, FCF_SNDR, conf.t2Timer, true);
     else {                                     // receive carrier not raised
        // The receiver will allow T2 to elapse intentionally here.
        // To keep recvFrame from timing out we double our wait.
-       framerecvd = recvFrame(frame, conf.t2Timer * 2);
+       framerecvd = recvFrame(frame, FCF_SNDR, conf.t2Timer * 2);
     }
 
     for (;;) {
@@ -169,7 +169,7 @@ Class1Modem::getPrologue(Class2Params& params, bool& hasDoc, fxStr& emsg, u_int&
                    }
                    break;
                }
-           } while (frame.moreFrames() && recvFrame(frame, conf.t2Timer));
+           } while (frame.moreFrames() && recvFrame(frame, FCF_SNDR, conf.t2Timer));
            if (frame.isOK()) {
                switch (frame.getRawFCF()) {
                case FCF_DIS:
@@ -210,7 +210,7 @@ Class1Modem::getPrologue(Class2Params& params, bool& hasDoc, fxStr& emsg, u_int&
         */
        if ((unsigned) Sys::now()-start >= t1)
            break;
-       framerecvd = recvFrame(frame, conf.t2Timer);
+       framerecvd = recvFrame(frame, FCF_SNDR, conf.t2Timer);
     }
     emsg = "No answer (T.30 T1 timeout)";
     protoTrace(emsg);
@@ -750,7 +750,7 @@ Class1Modem::sendTraining(Class2Params& params, int tries, fxStr& emsg)
             * FTT, or CFR; and also a premature DCN.
             */
            HDLCFrame frame(conf.class1FrameOverhead);
-           if (recvFrame(frame, conf.t4Timer)) {
+           if (recvFrame(frame, FCF_SNDR, conf.t4Timer)) {
                do {
                    switch (frame.getFCF()) {
                    case FCF_NSF:
@@ -760,7 +760,7 @@ Class1Modem::sendTraining(Class2Params& params, int tries, fxStr& emsg)
                        { fxStr csi; recvCSI(decodeTSI(csi, frame)); }
                        break;
                    }
-               } while (frame.moreFrames() && recvFrame(frame, conf.t4Timer));
+               } while (frame.moreFrames() && recvFrame(frame, FCF_SNDR, conf.t4Timer));
            } 
            if (frame.isOK()) {
                switch (frame.getFCF()) {
@@ -1144,7 +1144,7 @@ Class1Modem::blockFrame(const u_char* bitrev, bool lastframe, u_int ppmcmd, fxSt
                // in those cases waiting T2 for a response will cause the remote to
                // hang up.  So, using T4 here is imperative so that our second PPS
                // message happens before the remote decides to hang up.
-               if (gotppr = recvFrame(pprframe, conf.t4Timer)) {
+               if (gotppr = recvFrame(pprframe, FCF_SNDR, conf.t4Timer)) {
                    tracePPR("SEND recv", pprframe.getFCF());
                    if (pprframe.getFCF() == FCF_CRP) {
                        gotppr = false;
@@ -1186,7 +1186,7 @@ Class1Modem::blockFrame(const u_char* bitrev, bool lastframe, u_int ppmcmd, fxSt
                            stopTimeout("sending RR frame");
                            tracePPM("SEND send", FCF_RR);
                            // T.30 states that we must wait no more than T4 between unanswered RR signals.
-                           if (gotmsg = recvFrame(pprframe, conf.t4Timer)) {
+                           if (gotmsg = recvFrame(pprframe, FCF_SNDR, conf.t4Timer)) {
                                tracePPR("SEND recv", pprframe.getFCF());
                                if (pprframe.getFCF() == FCF_CRP) {
                                    gotmsg = false;
@@ -1310,7 +1310,7 @@ Class1Modem::blockFrame(const u_char* bitrev, bool lastframe, u_int ppmcmd, fxSt
                                    sendFrame(FCF_CTC|FCF_SNDR, fxStr(ctc, 2));
                                    stopTimeout("sending CTC frame");
                                    tracePPM("SEND send", FCF_CTC);
-                                   if (gotctr = recvFrame(ctrframe, conf.t4Timer)) {
+                                   if (gotctr = recvFrame(ctrframe, FCF_SNDR, conf.t4Timer)) {
                                        tracePPR("SEND recv", ctrframe.getFCF());
                                        if (ctrframe.getFCF() == FCF_CRP) {
                                            gotctr = false;
@@ -1363,7 +1363,7 @@ Class1Modem::blockFrame(const u_char* bitrev, bool lastframe, u_int ppmcmd, fxSt
                                    stopTimeout("sending EOR frame");
                                    tracePPM("SEND send", FCF_EOR);
                                    tracePPM("SEND send", pps[0]);
-                                   if (goterr = recvFrame(errframe, conf.t2Timer)) {
+                                   if (goterr = recvFrame(errframe, FCF_SNDR, conf.t2Timer)) {
                                        tracePPR("SEND recv", errframe.getFCF());
                                        if (errframe.getFCF() == FCF_CRP) {
                                            goterr = false;
@@ -1405,7 +1405,7 @@ Class1Modem::blockFrame(const u_char* bitrev, bool lastframe, u_int ppmcmd, fxSt
                                            stopTimeout("sending RR frame");
                                            tracePPM("SEND send", FCF_RR);
                                            // T.30 states that we must wait no more than T4 between unanswered RR signals.
-                                           if (gotmsg = recvFrame(errframe, conf.t2Timer)) {
+                                           if (gotmsg = recvFrame(errframe, FCF_SNDR, conf.t2Timer)) {
                                                tracePPR("SEND recv", errframe.getFCF());
                                                if (errframe.getFCF() == FCF_CRP) {
                                                    gotmsg = false;
@@ -1879,7 +1879,7 @@ Class1Modem::sendPPM(u_int ppm, HDLCFrame& mcf, fxStr& emsg)
 {
     for (int t = 0; t < 3; t++) {
        tracePPM("SEND send", ppm);
-       if (transmitFrame(ppm|FCF_SNDR) && recvFrame(mcf, conf.t4Timer))
+       if (transmitFrame(ppm|FCF_SNDR) && recvFrame(mcf, FCF_SNDR, conf.t4Timer))
            return (true);
        if (abortRequested())
            return (false);
index 17fb10fde5f3abce00c58ea42e6c7ce9b0749294..9de326bc511ee954e7656848a58c606c7524dd1d 100644 (file)
@@ -1382,7 +1382,7 @@ ModemServer::getModemLine(char rbuf[], u_int bufSize, long ms)
        while ((c = getModemChar(0)) != EOF && c != '\n')
            if (c != '\0' && c != '\r' && cc < bufSize)
                rbuf[cc++] = c;
-    } while (cc == 0 && c != EOF);
+    } while (!timer.wasTimeout() && cc == 0 && c != EOF);
     rbuf[cc] = '\0';
     if (ms) stopTimeout("reading line from modem");
     if (!timeout)