]> git.ipfire.org Git - thirdparty/HylaFAX.git/commitdiff
Bug 77: handle repeated PPS, DCS, or EOR signals from the sender
authorLee Howard <faxguy@howardsilvan.com>
Tue, 27 Apr 2004 04:49:41 +0000 (04:49 +0000)
committerLee Howard <faxguy@howardsilvan.com>
Tue, 27 Apr 2004 04:49:41 +0000 (04:49 +0000)
faxd/Class1.c++
faxd/Class1.h
faxd/Class1Recv.c++

index 8df83c74af405232b41b246ca0abb41d6c4d0b63..7736442d1164f0779021afa9836217bc7e8dd8e3 100644 (file)
@@ -493,6 +493,7 @@ Class1Modem::waitForDCEChannel(bool awaitctrl)
     fxStr garbage;
     bool gotresponse = false;
     gotRTNC = false;
+    ctrlFrameRcvd = fxStr::null;
     do {
        c = getModemChar(60000);
        if (c == DLE) {
@@ -566,6 +567,39 @@ Class1Modem::waitForDCEChannel(bool awaitctrl)
                    break;
            }
        } else garbage.append(c);
+       if (gotCTRL && garbage.length() > 2 && (garbage[0] & 0xFF) == 0xFF && 
+           (garbage[garbage.length()-2] & 0xFF) == 0x10 &&
+           (garbage[garbage.length()-1] & 0xFF) == 0x03) {
+           // We got a control frame and won't get the channel change...
+           for (u_int i = 0; i < garbage.length()-2; i++) {
+               if ((garbage[i] & 0xFF) == DLE && ++i < garbage.length()) {
+                   /*
+                    * We've got a frame and must apply T.31-A1 Table B.1.
+                    */
+                   if ((garbage[i] & 0xFF) == 0x07) {  // end of HDLC frame w/FCS error
+                       // what to do? send CRP? discard frame?
+                       continue;
+                   }
+                   switch (garbage[i] & 0xFF) {
+                       case DLE:       // <DLE><DLE> => <DLE>
+                           ctrlFrameRcvd.append(DLE);
+                           break;
+                       case SUB:       // <DLE><SUB> => <DLE><DLE>
+                           ctrlFrameRcvd.append(DLE);
+                           ctrlFrameRcvd.append(DLE);
+                           break;
+                       case 0x51:      // <DLE><0x51> => <DC1>
+                           ctrlFrameRcvd.append(DC1);
+                           break;
+                       case 0x53:      // <DLE><0x53> => <DC3>
+                           ctrlFrameRcvd.append(0x13);
+                           break;
+                   }
+               } else
+                   ctrlFrameRcvd.append(garbage[i] & 0xFF);
+           }
+           return (false);
+       }
        fxStr rcpsignal;
        rcpsignal.append(0xFF); rcpsignal.append(0x03); rcpsignal.append(0x86); rcpsignal.append(0x69);
        rcpsignal.append(0xCB); rcpsignal.append(0x10); rcpsignal.append(0x03);
index 0a6a56ce2b2d68d9a0fa40ab099b095f3acda551..264989c0dc2ee9bf798351f93a6aec4136690e40 100644 (file)
@@ -108,6 +108,7 @@ protected:
     bool       gotRTNC;        // retrain control channel
     u_short    primaryV34Rate; // rate indication for primary channel
     u_short    controlV34Rate; // rate indication for control channel
+    fxStr      ctrlFrameRcvd;  // unexpected control channel frame received
 
 // modem setup stuff
     virtual bool setupModem();
index 36c45048870205d5f1e5a52cecd1700e9599d4f6..8a67046ad3367a05d06dfafe01ee914c9a63ca5d 100644 (file)
@@ -791,18 +791,26 @@ Class1Modem::recvPageECMData(TIFF* tif, const Class2Params& params, fxStr& emsg)
                if (!gotEOT) {
                    bool gotprimary = waitForDCEChannel(false);
                    u_short rtnccnt = 0;
-                   while (!gotEOT && gotRTNC && rtnccnt++ < 3) {
+                   while (!gotEOT && (gotRTNC || (ctrlFrameRcvd != fxStr::null)) && rtnccnt++ < 3) {
                        /*
-                        * Remote requested control channel retrain; the remote
+                        * Remote requested control channel retrain and/or the remote
                         * didn't properly hear our last signal.  So now we have to
-                        * wait for a signal from the remote and then respond appropriately
+                        * use a signal from the remote and then respond appropriately
                         * to get us back in sync. DCS::CFR - PPS::PPR/MCF - EOR::ERR
                         */
                        if (flowControl == FLOW_XONXOFF)
                            (void) setXONXOFF(FLOW_NONE, FLOW_NONE, ACT_DRAIN);
                        setInputBuffering(false);
                        HDLCFrame rtncframe(conf.class1FrameOverhead);
-                       if (recvFrame(rtncframe, conf.t2Timer)) {
+                       bool gotrtncframe = false;
+                       if (ctrlFrameRcvd != fxStr::null) {
+                           gotrtncframe = true;
+                           for (u_int i = 0; i < ctrlFrameRcvd.length(); i++)
+                               rtncframe.put(frameRev[ctrlFrameRcvd[i] & 0xFF]);
+                           traceHDLCFrame("-->", rtncframe);
+                       } else
+                           gotrtncframe = recvFrame(rtncframe, conf.t2Timer);
+                       if (gotrtncframe) {
                            switch (rtncframe.getFCF()) {
                                case FCF_DCS:
                                    // hopefully it didn't change on us!
@@ -849,6 +857,11 @@ Class1Modem::recvPageECMData(TIFF* tif, const Class2Params& params, fxStr& emsg)
                                        }
                                    }
                                    break;
+                               case FCF_DCN:
+                                   tracePPM("RECV recv", rtncframe.getFCF());
+                                   gotEOT = true;
+                                   continue;
+                                   break;
                            }
                            setInputBuffering(true);
                            if (flowControl == FLOW_XONXOFF)