FaxModem.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:21k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: FaxModem.c++,v 1.20 2007/11/24 00:45:47 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1990-1996 Sam Leffler
  4.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  5.  * HylaFAX is a trademark of Silicon Graphics
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26. #include <ctype.h>
  27. #include <stdlib.h>
  28. #include "ClassModem.h"
  29. #include "FaxServer.h"
  30. #include "FaxTrace.h"
  31. #include "FaxFont.h"
  32. #include "t.30.h"
  33. #include "Sys.h"
  34. FaxModem::FaxModem(FaxServer& s, const ModemConfig& c)
  35.     : ClassModem(s,c)
  36.     , server(s)
  37. {
  38.     tagLineFont = NULL;
  39.     minsp = BR_2400;
  40.     curreq = NULL;
  41.     group3opts = 0;
  42.     imagefd = 0;
  43.     // fill order settings may be overwritten in derived class
  44.     recvFillOrder = (conf.recvFillOrder != 0)? conf.recvFillOrder : FILLORDER_LSB2MSB;
  45.     sendFillOrder = (conf.sendFillOrder != 0)? conf.sendFillOrder : FILLORDER_LSB2MSB;
  46.     rtcRev        = TIFFGetBitRevTable(sendFillOrder != FILLORDER_LSB2MSB);
  47.     pageNumberOfCall = 1;
  48. }
  49. FaxModem::~FaxModem()
  50. {
  51.     delete tagLineFont;
  52. }
  53. /*
  54.  * Default methods for modem driver interface.
  55.  */
  56. u_int FaxModem::getTagLineSlop() const { return tagLineSlop; }
  57. u_int FaxModem::getNoCountCoverPages()  { return noCountCoverPages; }
  58. /*
  59.  * Do setup work prior to placing the call.
  60.  */
  61. bool
  62. FaxModem::sendSetup(FaxRequest& req, const Class2Params&, fxStr&)
  63. {
  64.     minsp = fxmax((u_int) req.minbr, fxmax((u_int) conf.minSpeed, modemParams.getMinSpeed()));
  65.     pageNumber = 1;
  66.     pageNumberOfJob = req.npages + req.skippedpages - req.nocountcover + 1;
  67.     noCountCoverPages = req.nocountcover;
  68.     if (conf.useJobTagLine && req.desiredtl != 0)
  69. setupTagLine(req, req.tagline, conf.tagLineLocale);
  70.     else
  71. setupTagLine(req, conf.tagLineFmt, conf.tagLineLocale);
  72.     curreq = &req;
  73.     if (conf.setOriginCmd != "") {
  74. fxStr origincmd = conf.setOriginCmd;
  75. u_int numpos = origincmd.find(0, "%d");
  76. u_int nampos = origincmd.find(0, "%s");
  77. if (numpos == origincmd.length() && nampos == origincmd.length()) {
  78.     // neither %d nor %s appear in the cmd
  79.     if (!atCmd(origincmd)) return (false);
  80. } else if (numpos == origincmd.length()) {
  81.     // just %s appears in the cmd
  82.     if (!atCmd(fxStr::format((const char*) origincmd, (const char*) req.faxname))) return (false);
  83. } else if (nampos == origincmd.length()) {
  84.     // just %d appears in the cmd
  85.     origincmd[numpos+1] = 's'; // change %d to %s
  86.     if (!atCmd(fxStr::format((const char*) origincmd, (const char*) req.faxnumber))) return (false);
  87. } else {
  88.     // both %d and %s appear in the cmd
  89.     origincmd[numpos+1] = 's'; // change %d to %s
  90.     if (numpos < nampos) {
  91. // %d appears before %s
  92. if (!atCmd(fxStr::format((const char*) origincmd, (const char*) req.faxnumber, (const char*) req.faxname))) return (false);
  93.     } else {
  94. // %s appears before %d
  95. if (!atCmd(fxStr::format((const char*) origincmd, (const char*) req.faxname, (const char*) req.faxnumber))) return (false);
  96.     }
  97. }
  98.     }
  99.     return (true);
  100. }
  101. /*
  102.  * Do work at the beginning of a send operation;
  103.  * after a call has been established.
  104.  */
  105. void
  106. FaxModem::sendBegin()
  107. {
  108.     if (conf.sendBeginCmd != "")
  109. atCmd(conf.sendBeginCmd);
  110.     optFrames = 0;
  111. }
  112. void FaxModem::sendSetupPhaseB(const fxStr&, const fxStr&){}
  113. void FaxModem::sendEnd() {}
  114. bool
  115. FaxModem::recvBegin(FaxSetup*, fxStr&)
  116. {
  117.     optFrames = 0;
  118.     return (true);
  119. }
  120. bool
  121. FaxModem::recvEOMBegin(FaxSetup*, fxStr&)
  122. {
  123.     optFrames = 0;
  124.     return (true);
  125. }
  126. bool
  127. FaxModem::pollBegin(const fxStr&, const fxStr&, const fxStr&, fxStr&)
  128. {
  129.     optFrames = 0;
  130.     return (true);
  131. }
  132. /*
  133.  * Issue a command upon successful reception.
  134.  */
  135. void
  136. FaxModem::recvSucceeded()
  137. {
  138.     if (conf.recvSuccessCmd != "")
  139. atCmd(conf.recvSuccessCmd, AT_OK);
  140. }
  141. static void
  142. stripBlanks(fxStr& d, const fxStr& s)
  143. {
  144.     d = s;
  145.     d.remove(0, d.skip(0,' ')); // strip leading white space
  146.     u_int pos = d.skipR(d.length(),' ');
  147.     d.remove(pos, d.length() - pos); // and trailing white space
  148. }
  149. void
  150. FaxModem::recvTSI(const fxStr& s)
  151. {
  152.     stripBlanks(tsi, s);
  153.     protoTrace("REMOTE TSI "%s"", (const char*) tsi);
  154.     optFrames |= 0x1;
  155. }
  156. void
  157. FaxModem::recvCSI(const fxStr& s)
  158. {
  159.     stripBlanks(tsi, s);
  160.     protoTrace("REMOTE CSI "%s"", (const char*) tsi);
  161.     optFrames |= 0x1;
  162. }
  163. bool
  164. FaxModem::getRecvTSI(fxStr& s)
  165. {
  166.     if (optFrames & 0x1) {
  167. s = tsi;
  168. return (true);
  169.     } else
  170. return (false);
  171. }
  172. bool FaxModem::getSendCSI(fxStr& s) { return getRecvTSI(s); }
  173. void
  174. FaxModem::recvPWD(const fxStr& s)
  175. {
  176.     stripBlanks(pwd, s);
  177.     protoTrace("REMOTE PWD "%s"", (const char*) pwd);
  178.     optFrames |= 0x2;
  179. }
  180. bool
  181. FaxModem::getRecvPWD(fxStr& s)
  182. {
  183.     if (optFrames & 0x2) {
  184. s = pwd;
  185. return (true);
  186.     } else
  187. return (false);
  188. }
  189. void
  190. FaxModem::recvSUB(const fxStr& s)
  191. {
  192.     stripBlanks(sub, s);
  193.     protoTrace("REMOTE SUB "%s"", (const char*) sub);
  194.     optFrames |= 0x4;
  195. }
  196. bool
  197. FaxModem::getRecvSUB(fxStr& s)
  198. {
  199.     if (optFrames & 0x4) {
  200. s = sub;
  201. return (true);
  202.     } else
  203. return (false);
  204. }
  205. void
  206. FaxModem::recvNSF( const NSF& aNsf )
  207. {
  208.     nsf = aNsf;
  209.     optFrames |= 0x8;
  210.     protoTrace("REMOTE NSF "%s"", (const char*) nsf.getHexNsf() );
  211.     protoTrace("NSF remote fax equipment: %s %s", 
  212.                (const char*)nsf.getVendor(),
  213.                (const char*)nsf.getModel());
  214.     if( nsf.stationIdFound() )
  215.         protoTrace("NSF %sremote station ID: "%s"",
  216.                    nsf.vendorFound()? "": "possible ",
  217.                    nsf.getStationId());
  218. }
  219. bool
  220. FaxModem::getSendNSF(NSF& aNsf)
  221. {
  222.     if (optFrames & 0x8) {
  223.         aNsf = nsf;
  224.         return (true);
  225.     } else {
  226.         return (false);
  227.     }
  228. }
  229. void
  230. FaxModem::recvDCS(const Class2Params& params)
  231. {
  232.     protoTrace("REMOTE wants %s", params.bitRateName());
  233.     protoTrace("REMOTE wants %s", params.pageWidthName());
  234.     protoTrace("REMOTE wants %s", params.pageLengthName());
  235.     protoTrace("REMOTE wants %s", params.verticalResName());
  236.     protoTrace("REMOTE wants %s", params.dataFormatName());
  237.     if (params.ec != EC_DISABLE)
  238. protoTrace("REMOTE wants %s", params.ecmName());
  239. }
  240. const Class2Params& FaxModem::getRecvParams() const { return params; }
  241. /*
  242.  * Decode the post-page-handling string to get page
  243.  * chopping information for the current page.  The
  244.  * page chop information is optional and always
  245.  * precedes the page-handling information, so at least
  246.  * 2+5+1 characters must be present.  The format of the
  247.  * information is:
  248.  *
  249.  *   xxZcccxM
  250.  *
  251.  * xx is the hex-encoded session parameters (see below),
  252.  * M is a post-page message, and cccc is an optional 4-digit
  253.  * hex encoding of the number of bytes to chop from the
  254.  * encoded page data.  Note also that we only return the
  255.  * chop count if the negotiated session parameters permit
  256.  * us to send a variable-length page.
  257.  */ 
  258. u_int
  259. FaxModem::decodePageChop(const fxStr& pph, const Class2Params& params)
  260. {
  261.     if (params.ln == LN_INF && pph.length() >= 2+5+1 && pph[2] == 'Z') {
  262. char buf[5];
  263. buf[0] = pph[2+1];
  264. buf[1] = pph[2+2];
  265. buf[2] = pph[2+3];
  266. buf[3] = pph[2+4];
  267. buf[4] = '';
  268. return ((u_int) strtoul(buf, NULL, 16));
  269.     } else
  270. return (0);
  271. }
  272. /*
  273.  * Decode the post-page-handling string to get the next
  274.  * post-page message.  The string is assumed to have 3
  275.  * characters per page of the form:
  276.  *
  277.  *   xxM
  278.  *
  279.  * where xx is a 2-digit hex encoding of the session
  280.  * parameters required to send the page data and the M
  281.  * the post-page message to use between this page and
  282.  * the next page.  See FaxServer::sendPrepareFax for the
  283.  * construction of this string.
  284.  */ 
  285. bool
  286. FaxModem::decodePPM(const fxStr& pph, u_int& ppm, fxStr& emsg)
  287. {
  288.     const char* what;
  289.     if (pph.length() >= 3 && (pph[2] != 'Z' || pph.length() >= 2+5+1)) {
  290. switch (pph[pph[2] == 'Z' ? 2+5 : 2+0]) {
  291. case 'P': ppm = PPM_EOP; return (true);
  292. case 'M': ppm = PPM_EOM; return (true);
  293. case 'S': ppm = PPM_MPS; return (true);
  294. }
  295. what = "unknown";
  296.     } else
  297. what = "bad";
  298.     emsg = fxStr::format( "Internal botch; %s post-page handling string "%s" {E303}",
  299. what, (const char*) pph);
  300.     return (false);
  301. }
  302. /*
  303.  * Modem capability (and related) query interfaces.
  304.  */
  305. u_int
  306. FaxModem::getCapabilities() const
  307. {
  308.     return modemParams.encodeCaps();
  309. }
  310. static u_int
  311. bestBit(u_int bits, u_int top, u_int bot)
  312. {
  313.     while (top > bot && (bits & BIT(top)) == 0)
  314. top--;
  315.     return (top);
  316. }
  317. /*
  318.  * Return Class 2 code for best modem signalling rate.
  319.  */
  320. u_int
  321. FaxModem::getBestSignallingRate() const
  322. {
  323.     return bestBit(modemParams.br, BR_33600, BR_2400);
  324. }
  325. /*
  326.  * Compare the requested signalling rate against
  327.  * those the modem can do and return the appropriate
  328.  * Class 2 bit rate code.
  329.  */
  330. int
  331. FaxModem::selectSignallingRate(int br) const
  332. {
  333.     for (; br >= 0 && (modemParams.br & BIT(br)) == 0; br--)
  334. ;
  335.     return (br);
  336. }
  337. /*
  338.  * Compare the requested min scanline time
  339.  * to what the modem can do and return the
  340.  * lowest time the modem can do.
  341.  */
  342. int
  343. FaxModem::selectScanlineTime(int st) const
  344. {
  345.     for (; st < ST_40MS && (modemParams.st & BIT(st)) == 0; st++)
  346. ;
  347.     return (st);
  348. }
  349. /*
  350.  * Return the best min scanline time the modem
  351.  * is capable of supporting.
  352.  */
  353. u_int
  354. FaxModem::getBestScanlineTime() const
  355. {
  356.     u_int st;
  357.     for (st = ST_0MS; st < ST_40MS; st++)
  358. if (modemParams.st & BIT(st))
  359.     break;
  360.     return st;
  361. }
  362. /*
  363.  * Return the best vres the modem supports.
  364.  */
  365. u_int
  366. FaxModem::getVRes() const
  367. {
  368.     /*
  369.      * We don't use bestBit() here because T.32 Table 21
  370.      * states that VR is to be reported as a bitmask
  371.      * of supported resolutions.  So we already have it.
  372.      */
  373.     return (modemParams.vr);
  374. }
  375. /*
  376.  * Return the best page width the modem supports.
  377.  */
  378. u_int
  379. FaxModem::getBestPageWidth() const
  380. {
  381.     // XXX NB: we don't use anything > WD_A3
  382.     return bestBit(modemParams.wd, WD_A3, WD_A4);
  383. }
  384. /*
  385.  * Return the best page length the modem supports.
  386.  */
  387. u_int
  388. FaxModem::getBestPageLength() const
  389. {
  390.     return bestBit(modemParams.ln, LN_INF, LN_A4);
  391. }
  392. /*
  393.  * Return the best data format the modem supports.
  394.  */
  395. u_int
  396. FaxModem::getBestDataFormat() const
  397. {
  398.     return bestBit(modemParams.df, DF_JBIG, DF_1DMH);
  399. }
  400. /*
  401.  * Return the best ECM functionality the modem supports.
  402.  */
  403. u_int
  404. FaxModem::getBestECM() const
  405. {
  406.     return bestBit(modemParams.ec, EC_ECLFULL, EC_DISABLE);
  407. }
  408. /*
  409.  * Return whether or not the modem supports 2DMR.
  410.  */
  411. bool
  412. FaxModem::supports2D() const
  413. {
  414.     return (modemParams.df & BIT(DF_2DMR)) != 0;
  415. }
  416. /*
  417.  * Return whether or not the modem supports 2DMMR.
  418.  */
  419. bool
  420. FaxModem::supportsMMR() const
  421. {
  422.     return (modemParams.df & BIT(DF_2DMMR)) != 0;
  423. }
  424. /*
  425.  * Return whether or not the modem supports JBIG.
  426.  */
  427. bool
  428. FaxModem::supportsJBIG() const
  429. {
  430.     return (modemParams.df & BIT(DF_JBIG)) != 0;
  431. }
  432. /*
  433.  * Return whether or not received EOLs are byte aligned.
  434.  */
  435. bool
  436. FaxModem::supportsEOLPadding() const
  437. {
  438.     return false;
  439. }
  440. /*
  441.  * Return whether or not the modem is capable of polling.
  442.  */
  443. bool
  444. FaxModem::supportsPolling() const
  445. {
  446.     return false;
  447. }
  448. /*
  449.  * Return whether or not the modem supports
  450.  * the optional Error Correction Mode (ECM).
  451.  */
  452. bool
  453. FaxModem::supportsECM(u_int ec) const
  454. {
  455.     if (ec)
  456. return (modemParams.ec & BIT(ec)) != 0;
  457.     else // supports "any ecm"
  458. return (modemParams.ec &~ BIT(EC_DISABLE)) != 0;
  459. }
  460. /*
  461.  * Return whether or not the modem supports the
  462.  * specified vertical resolution.  Note that we're
  463.  * rather tolerant because of potential precision
  464.  * problems and general sloppiness on the part of
  465.  * applications writing TIFF files.
  466.  *
  467.  * Because R8 and R16 vertical resolutions are the same
  468.  * but differ by horizontal resolution, R16 is "coded"
  469.  * as "20" in order to support it.
  470.  */
  471. bool
  472. FaxModem::supportsVRes(float res) const
  473. {
  474.     if (3.0 <= res && res < 4.75)
  475. return ((modemParams.vr & VR_NORMAL) || (modemParams.vr & VR_200X100)) != 0;
  476.     else if (5.9 <= res && res < 9.8)
  477. return ((modemParams.vr & VR_FINE) || (modemParams.vr & VR_200X200)) != 0;
  478.     else if (9.8 <= res && res < 13)
  479. return (modemParams.vr & VR_300X300) != 0;
  480.     else if (13 <= res && res < 19)
  481. return ((modemParams.vr & VR_R8) || (modemParams.vr & VR_200X400)) != 0;
  482.     else if (res == 20)
  483. return (modemParams.vr & VR_R16) != 0;
  484.     else
  485. return false;
  486. }
  487. /*
  488.  * Return whether or not the modem supports the
  489.  * specified page width.
  490.  */
  491. bool
  492. FaxModem::supportsPageWidth(u_int w, u_int r) const
  493. {
  494.     switch (r) {
  495. case VR_R16:
  496.     switch (w) {
  497. case 3456:   return (modemParams.wd & BIT(WD_A4)) != 0;
  498. case 4096:   return (modemParams.wd & BIT(WD_B4)) != 0;
  499. case 4864:   return (modemParams.wd & BIT(WD_A3)) != 0;
  500.     }
  501. case VR_300X300:
  502.     switch (w) {
  503. case 2592:   return (modemParams.wd & BIT(WD_A4)) != 0;
  504. case 3072:   return (modemParams.wd & BIT(WD_B4)) != 0;
  505. case 3648:   return (modemParams.wd & BIT(WD_A3)) != 0;
  506.     }
  507. case VR_NORMAL:
  508. case VR_FINE:
  509. case VR_R8:
  510. case VR_200X100:
  511. case VR_200X200:
  512. case VR_200X400:
  513.     switch (w) {
  514. case 1728:   return (modemParams.wd & BIT(WD_A4)) != 0;
  515. case 2048:   return (modemParams.wd & BIT(WD_B4)) != 0;
  516. case 2432:   return (modemParams.wd & BIT(WD_A3)) != 0;
  517.     }
  518.     }
  519.     return false;
  520. }
  521. /*
  522.  * Return whether or not the modem supports the
  523.  * specified page length.  As above for vertical
  524.  * resolution we're lenient in what we accept.
  525.  */
  526. bool
  527. FaxModem::supportsPageLength(u_int l) const
  528. {
  529.     // XXX probably need to be more forgiving with values
  530.     if (270 < l && l <= 330)
  531. return (modemParams.ln & (BIT(LN_A4)|BIT(LN_INF))) != 0;
  532.     else if (330 < l && l <= 390)
  533. return (modemParams.ln & (BIT(LN_B4)|BIT(LN_INF))) != 0;
  534.     else
  535. return (modemParams.ln & BIT(LN_INF)) != 0;
  536. }
  537. /*
  538.  * Return modems best capabilities for setting up
  539.  * the initial T.30 DIS when receiving data.
  540.  */
  541. FaxParams
  542. FaxModem::modemDIS() const
  543. {
  544.     Class2Params tmp(modemParams);
  545.     tmp.update(true);
  546.     return tmp;
  547. }
  548. /*
  549.  * Tracing support.
  550.  */
  551. /*
  552.  * Trace a modem's capabilities.
  553.  */
  554. void
  555. FaxModem::traceModemParams()
  556. {
  557.     traceBitMask(modemParams.vr, Class2Params::verticalResNames);
  558.     traceBits(modemParams.br, Class2Params::bitRateNames);
  559.     traceBits(modemParams.wd, Class2Params::pageWidthNames);
  560.     traceBits(modemParams.ln, Class2Params::pageLengthNames);
  561.     u_int dataforms = modemParams.df + ((modemParams.jp & (BIT(JP_GREY) | BIT(JP_COLOR))) << 4);
  562.     traceBits(dataforms, Class2Params::dataFormatNames);
  563.     if (supportsECM())
  564. traceBits(modemParams.ec, Class2Params::ecmNames);
  565.     if (modemParams.bf & BIT(BF_ENABLE))
  566. modemSupports("binary file transfer");
  567.     traceBits(modemParams.st, Class2Params::scanlineTimeNames);
  568. }
  569. void
  570. FaxModem::traceFCF(const char* dir, u_int fcf)
  571. {
  572.     const char* fcfname;
  573.     switch (fcf & 0x7F) {
  574. case 0x00:
  575.     fcfname = "NULL (more blocks, same page)";
  576.     break;
  577. case FCF_DIS:
  578.     fcfname = "DIS (identification signal)";
  579.     break;
  580. case FCF_DCS:
  581.     fcfname = "DCS (command signal)";
  582.     break;
  583. case FCF_CSI:
  584.     fcfname = "CSI (called subscriber id)";
  585.     break;
  586. case FCF_TSI:
  587.     fcfname = "TSI (sender id)";
  588.     break;
  589. case FCF_CFR:
  590.     fcfname = "CFR (confirmation to receive)";
  591.     break;
  592. case FCF_FTT:
  593.     fcfname = "FTT (failure to train)";
  594.     break;
  595. case FCF_CRP:
  596.     fcfname = "CRP (command repeat)";
  597.     break;
  598. case FCF_EOM:
  599.     fcfname = "EOM (more documents)";
  600.     break;
  601. case FCF_MPS:
  602.     fcfname = "MPS (more pages, same document)";
  603.     break;
  604. case FCF_EOR:
  605.     fcfname = "EOR (end of retransmission)";
  606.     break;
  607. case FCF_EOP:
  608.     fcfname = "EOP (no more pages or documents)";
  609.     break;
  610. case FCF_RR:
  611.     fcfname = "RR (receive ready)";
  612.     break;
  613. case FCF_CTC:
  614.     fcfname = "CTC (continue to correct)";
  615.     break;
  616. case FCF_PRI_EOM:
  617.     fcfname = "PRI-EOM (more documents after interrupt)";
  618.     break;
  619. case FCF_PRI_MPS:
  620.     fcfname = "PRI-MPS (more pages after interrupt)";
  621.     break;
  622. case FCF_PRI_EOP:
  623.     fcfname = "PRI-EOP (no more pages after interrupt)";
  624.     break;
  625. case FCF_PPS:
  626.     fcfname = "PPS (partial page signal)";
  627.     break;
  628. case FCF_DCN:
  629.     fcfname = "DCN (disconnect)";
  630.     break;
  631. case FCF_CTR:
  632.     fcfname = "CTR (confirm continue to correct)";
  633.     break;
  634. case FCF_NSF:
  635.     fcfname = "NSF (non-standard facilities)";
  636.     break;
  637. case FCF_NSS:
  638.     fcfname = "NSS (non-standard setup)";
  639.     break;
  640. case FCF_MCF:
  641.     fcfname = "MCF (message confirmation)";
  642.     break;
  643. case FCF_RTN:
  644.     fcfname = "RTN (retrain negative)";
  645.     break;
  646. case FCF_RTP:
  647.     fcfname = "RTP (retrain positive)";
  648.     break;
  649. case FCF_PIN:
  650.     fcfname = "PIN (procedural interrupt negative)";
  651.     break;
  652. case FCF_PIP:
  653.     fcfname = "PIP (procedural interrupt positive)";
  654.     break;
  655. case FCF_RNR:
  656.     fcfname = "RNR (receive not ready)";
  657.     break;
  658. case FCF_ERR:
  659.     fcfname = "ERR (confirm end of retransmisison)";
  660.     break;
  661. case FCF_PPR:
  662.     fcfname = "PPR (partial page request)";
  663.     break;
  664. case FCF_SUB:
  665.     fcfname = "SUB (subaddress)";
  666.     break;
  667. case FCF_PWD:
  668.     fcfname = "PWD (password)";
  669.     break;
  670. default:
  671.     protoTrace("unknown FCF 0x%X", fcf);
  672.     return;
  673.     }
  674.     protoTrace("%s %s", dir, (const char*) fcfname);
  675. }
  676. /*
  677.  * Modem i/o support.
  678.  */
  679. /*
  680.  * Miscellaneous server interfaces hooks.
  681.  */
  682. bool FaxModem::isFaxModem() const { return true; }
  683. bool FaxModem::getHDLCTracing()
  684.     { return (server.getSessionTracing() & FAXTRACE_HDLC) != 0; }
  685. bool FaxModem::getECMTracing()
  686.     { return (server.getSessionTracing() & FAXTRACE_ECM) != 0; }
  687. FaxSendStatus
  688. FaxModem::sendSetupParams(TIFF* tif, Class2Params& params,
  689.     FaxMachineInfo& info, fxStr& emsg)
  690. {
  691.     return server.sendSetupParams(tif, params, info, emsg);
  692. }
  693. /*
  694.  * Record the file offset to the start of the data
  695.  * in the file.  We write zero bytes to force the
  696.  * strip offset to be setup in case this is the first
  697.  * time the strip is being written.
  698.  */
  699. void
  700. FaxModem::recvStartPage(TIFF* tif)
  701. {
  702.     u_char null[1];
  703.     (void) TIFFWriteRawStrip(tif, 0, null, 0);
  704.     (void) TIFFGetField(tif, TIFFTAG_STRIPOFFSETS, &savedWriteOff);
  705.     (void) TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &savedStripByteCounts);
  706.     pageStarted = true;
  707. }
  708. /*
  709.  * Reset the TIFF state for the current page so that
  710.  * subsequent data overwrites anything previously
  711.  * written.  This is done by reseting the file offset
  712.  * and setting the strip's bytecount and offset to
  713.  * values they had at the start of the page.  This
  714.  * scheme assumes that only page data is written to
  715.  * the file between the time recvSetupPage is called
  716.  * and recvResetPage is called.
  717.  */
  718. void
  719. FaxModem::recvResetPage(TIFF* tif)
  720. {
  721.     if (!pageStarted) return;
  722.     TIFFSetWriteOffset(tif, 0); // force library to reset state
  723.     TIFFSetField(tif, TIFFTAG_STRIPOFFSETS, savedWriteOff);
  724.     TIFFSetField(tif, TIFFTAG_STRIPBYTECOUNTS, savedStripByteCounts);
  725. }
  726. void
  727. FaxModem::countPage()
  728. {
  729.     pageNumber++;
  730.     pageNumberOfJob++;
  731.     pageNumberOfCall++;
  732.     if (noCountCoverPages > 0) noCountCoverPages--;
  733. }
  734. int
  735. FaxModem::getPageNumberOfCall()
  736. {
  737.     return pageNumberOfCall;
  738. }
  739. void
  740. FaxModem::notifyPageSent(TIFF* tif)
  741. {
  742.     if (curreq)
  743. server.notifyPageSent(*curreq, TIFFFileName(tif));
  744. }
  745. #include "MemoryDecoder.h"
  746. void
  747. FaxModem::correctPhaseCData(u_char* buf, u_long& pBufSize,
  748.                             u_int fillorder, const Class2Params& params, uint32& rows)
  749. {
  750.     u_char* endOfData;
  751.     MemoryDecoder dec1(buf, params.pageWidth(), pBufSize, fillorder, params.is2D(), false);
  752.     dec1.fixFirstEOL();
  753.     /*
  754.      * We have to construct new decoder. See comments to cutExtraRTC().
  755.      */
  756.     MemoryDecoder dec2(buf, params.pageWidth(), pBufSize, fillorder, params.is2D(), false);
  757.     endOfData = dec2.cutExtraRTC();
  758.     // we don't update rows because we don't decode the entire image
  759.     if( endOfData )
  760.         pBufSize = endOfData - buf;
  761. }
  762. u_char*
  763. FaxModem::convertPhaseCData(u_char* buf, u_long& totdata, u_int fillorder, 
  764.     const Class2Params& params, const Class2Params& newparams, uint32& rows)
  765. {
  766.     MemoryDecoder dec(buf, params.pageWidth(), totdata, fillorder, params.is2D(), (params.df == DF_2DMMR));
  767.     u_char* data = dec.convertDataFormat(newparams);
  768.     totdata = dec.getCC();
  769.     rows = dec.getRows();
  770.     return (data);
  771. }