Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2164 lines
82 KiB

  1. /***************************************************************************
  2. Name : T30.C
  3. Comment : Contains the main T30 routine, which drives this whole baby.
  4. It calls the user-supplied protocol function to make all the
  5. protocol decision functions. Thus in a sense this merely
  6. a hollow shell.
  7. This file should be read together with the appropriate
  8. protocol function that is in use, and the T30 flowchart
  9. (the enhanced one which includes ECM that is supplied in
  10. T.30 Appendix-A). Ideally the (paper) copy of the chart
  11. which I've annotated to chow which nodes are implemented
  12. in the protocol callback function.
  13. The other routines contained here implement the T.30
  14. flowchart "subroutines" labelled "Response Received"
  15. "Command Received", "RR Response Received" and "CTC
  16. Response Received". All of which are called (only)
  17. from ET30MainBody().
  18. Most of teh real work is farmed out to HDLC.C (and macros
  19. in HDLC.H), so the T30 routine is reasonably lucid.
  20. It's organized as a block of statements with gotos between
  21. them to closely mirror the T30 flowchart. (It's actually
  22. uncannily close!)
  23. Functions: (see Prototypes just below)
  24. Revision Log
  25. Date Name Description
  26. -------- ----- ---------------------------------------------------------
  27. 06/14/92 arulm Created it in the new incarnation for the first time. The
  28. T30Main() function is re-written to call WhatNext() at *all*
  29. decision points. Some parts are simplified. It bears some
  30. resemblance to the original. Command/ResponseReceived is
  31. completely re-written.
  32. 06/15/92 arulm Added ECM. Still havn't tried compiling it.
  33. 06/16/92 arulm First successful compile.
  34. ***************************************************************************/
  35. #define USE_DEBUG_CONTEXT DEBUG_CONTEXT_T30_MAIN
  36. #include "prep.h"
  37. #include "efaxcb.h"
  38. #include "t30.h"
  39. #include "hdlc.h"
  40. #include "..\comm\modemint.h"
  41. #include "..\comm\fcomint.h"
  42. #include "..\comm\mdmcmds.h"
  43. #include "debug.h"
  44. #include "tiff.h"
  45. #include "glbproto.h"
  46. #include "t30gl.h"
  47. #include "psslog.h"
  48. #define FILE_ID FILE_ID_T30
  49. /***************************************************************************
  50. Name : ET30MainBody
  51. Purpose : This is the main T30. It's main purpose is to faithfully
  52. reproduce the flowchart on pages 100-103 of Fascicle VII.3
  53. of the CCITT blue book, Recomendation T30.
  54. It is to be called from the protocol module after a call has
  55. been successfully placed or answered & the modem is in HDLC
  56. receive or send mode respectively. It conducts the entire call,
  57. making callbacks at all decision points to a protocol-supplied
  58. callback function. It also calls protocol-supplied callback
  59. functions to get data to send and to unload received data.
  60. Returns : When it returns, the phone is on hook & the modem reset.
  61. It returns TRUE on successful call completion, and FALSE on
  62. error. In all cases, GetLastError() will return the completion
  63. status.
  64. Arguments:
  65. Comment : This function is supposed to mirror the brain-dead flowchart
  66. so it is structured as a series of statement blocks and a rats
  67. nest of Gotos. Yes I hate GOTOs too. Havn't used one in years,
  68. but try to do this yourself sometime in a "structured" way.
  69. The Labels used are the same as those used in the Flowchart, and
  70. the blocks are arranged in approximately teh same order as in
  71. the chart, so reading both together will be a pleasant surprise.
  72. Make sure you use the chart in the __APPENDIX-A__ of the
  73. **1988** (or Blue Book) CCITT specs. The chart in teh main body
  74. of teh spec is (a) deceptively similar (b) out-of-date
  75. Calls : All of HDLC.C, some of MODEM.C, and a little of FCOM.C.
  76. all the rest of the functions in this file.
  77. Called By:
  78. Revision Log
  79. Date Name Description
  80. -------- ----- ---------------------------------------------------------
  81. 06/15/92 arulm Adding ECM. Making it compilable
  82. ***************************************************************************/
  83. #define T1_TIMEOUT 40000L // 35s + 5s. On PCs be more lax
  84. // #define T2_TIMEOUT 7000 // 6s + 1s
  85. #define T2_TIMEOUT 6000 // 6s
  86. // #define T4_TIMEOUT 3450 // 3s + 15%
  87. #define T4_TIMEOUT 3000 // 3s
  88. // #define T4_TIMEOUT 2550 // 3s - 15%
  89. // if our DCS-TCF collides with the recvrs 2nd NSF-DIS or NSC-DTC
  90. // then if the lengths are just right, we can end up in lock step
  91. // after the first try, increase the TCF-response timeout so we
  92. // get out of lock step! This is bug#6847
  93. #define TCFRESPONSE_TIMEOUT_SLACK 500 // 0.5 secs
  94. /****************** begin prototypes from t30.c *****************/
  95. ET30ACTION PhaseNodeA(PThrdGlbl pTG);
  96. ET30ACTION PhaseNodeT(PThrdGlbl pTG);
  97. ET30ACTION PhaseNodeD(PThrdGlbl pTG);
  98. ET30ACTION NonECMPhaseC(PThrdGlbl pTG );
  99. ET30ACTION NonECMPhaseD(PThrdGlbl pTG );
  100. ET30ACTION RecvPhaseB(PThrdGlbl pTG, ET30ACTION action);
  101. ET30ACTION PhaseNodeF(PThrdGlbl pTG, BOOL);
  102. ET30ACTION PhaseRecvCmd(PThrdGlbl pTG );
  103. ET30ACTION PhaseGetTCF(PThrdGlbl pTG, IFR);
  104. ET30ACTION NonECMRecvPhaseC(PThrdGlbl pTG);
  105. ET30ACTION NonECMRecvPhaseD(PThrdGlbl pTG);
  106. /***************** end of prototypes from t30.c *****************/
  107. USHORT T30MainBody
  108. (
  109. PThrdGlbl pTG,
  110. BOOL fCaller
  111. )
  112. {
  113. ET30ACTION action;
  114. USHORT uRet;
  115. DEBUG_FUNCTION_NAME(_T("T30MainBody"));
  116. uRet = T30_CALLFAIL;
  117. _fmemset(&pTG->T30, 0, sizeof(pTG->T30));
  118. _fmemset(&pTG->EchoProtect, 0, sizeof(pTG->EchoProtect));
  119. // Initialize this global. Very Important!! See HDLC.C for usage.
  120. pTG->T30.fReceivedDIS = FALSE;
  121. pTG->T30.fReceivedDTC = FALSE;
  122. pTG->T30.fReceivedEOM = FALSE;
  123. pTG->T30.uTrainCount = 0;
  124. pTG->T30.uRecvTCFMod = 0xFFFF;
  125. pTG->T30.ifrCommand = pTG->T30.ifrResp = pTG->T30.ifrSend = 0;
  126. pTG->T30.fAtEndOfRecvPage = FALSE;
  127. pTG->T30.lpfs = (LPFRAMESPACE)pTG->bStaticRecvdFrameSpace;
  128. pTG->T30.Nframes = 0;
  129. if(fCaller) // choose the right entry point
  130. {
  131. action = actionGONODE_T;
  132. }
  133. else
  134. {
  135. action = actionGONODE_R1;
  136. }
  137. // fall through into PhaseLoop
  138. if (pTG->fAbortRequested)
  139. {
  140. goto error;
  141. }
  142. /******** Phase loop ********/
  143. //PhaseLoop:
  144. for(;;)
  145. {
  146. /******************************************************************************
  147. T = Start of Phase be for transmitter
  148. R1 = Start of Phase B for callee
  149. R2 = start of Phase B for poller
  150. A = Poll/Send decision point
  151. D = Start of DCS/TCF
  152. F = Recv Command loop
  153. RecvCmd = Interpretation of pre-page cmds
  154. RecvPhaseC = Start of Rx PhaseC (ECM and Non-pTG->ECM. New Page in ECM mode)
  155. I = Start of Tx PhaseC (ECM & Non-pTG->ECM. New page in ECM mode)
  156. II = Start of Tx Non-ECM PhaseD
  157. III = Start of Rx Non-ECM PhaseD
  158. IV = Start of Tx ECM PhaseC (Same page, new block)
  159. V = Start of Tx ECM PhaseD (end of partial page)
  160. VII = Start of Rx ECM PhaseD
  161. RecvPRIQ = Handling of recvd PRI-Q commands
  162. E = Handling of received PIP/PIN responses
  163. *******************************************************************************/
  164. switch(action)
  165. {
  166. case actionGONODE_T:
  167. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_T");
  168. PSSLogEntry(PSS_MSG, 0, "Phase B - Negotiation");
  169. action = PhaseNodeT(pTG);
  170. break;
  171. case actionGONODE_D:
  172. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_D");
  173. action = PhaseNodeD(pTG);
  174. break;
  175. case actionGONODE_A:
  176. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_A");
  177. action = PhaseNodeA(pTG);
  178. break;
  179. case actionGONODE_R1:
  180. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_R1");
  181. PSSLogEntry(PSS_MSG, 0, "Phase B - Negotiation");
  182. action = RecvPhaseB(pTG, action);
  183. break;
  184. case actionNODEF_SUCCESS:
  185. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionNODEF_SUCCESS");
  186. action = PhaseNodeF(pTG, TRUE);
  187. break;
  188. case actionGONODE_F:
  189. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_F");
  190. action = PhaseNodeF(pTG, FALSE);
  191. break;
  192. case actionGONODE_RECVCMD:
  193. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_RECVCMD");
  194. action = PhaseRecvCmd(pTG);
  195. break;
  196. case actionGONODE_I:
  197. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_I");
  198. action = NonECMPhaseC(pTG);
  199. break;
  200. case actionGONODE_II:
  201. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_II");
  202. action = NonECMPhaseD(pTG);
  203. break;
  204. case actionGONODE_III:
  205. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_III");
  206. action = NonECMRecvPhaseD(pTG);
  207. break;
  208. case actionGONODE_RECVPHASEC:
  209. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionGONODE_RECVPHASEC");
  210. action = NonECMRecvPhaseC(pTG);
  211. break;
  212. case actionNULL:
  213. goto error;
  214. case actionDCN_SUCCESS:
  215. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionDCN_SUCCESS");
  216. uRet = T30_CALLDONE;
  217. goto NodeC; // successful end of send call
  218. case actionHANGUP_SUCCESS:
  219. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionHANGUP_SUCCESS");
  220. uRet = T30_CALLDONE;
  221. goto done; // successful end of recv call
  222. case actionDCN:
  223. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionDCN");
  224. goto NodeC;
  225. case actionHANGUP:
  226. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionHANGUP");
  227. // This should only be called on a _successful_ completion,
  228. // otherwise we get either (a) a DCN that MSGHNDLR does not
  229. // want OR (b) A fake EOJ posted to MSGHNDLR. See bug#4019
  230. goto done;
  231. case actionERROR:
  232. DebugPrintEx(DEBUG_MSG,"EndPhase: Got actionERROR");
  233. goto error;
  234. default:
  235. goto error;
  236. }
  237. }
  238. error:
  239. DebugPrintEx( DEBUG_ERR,
  240. "=======******* USER ABORT or TRANSPORT FATAL ERROR *******========");
  241. // must call this always, because it's resets the Modem Driver's
  242. // global state (e.g. shuts down SW framing & filters if open,
  243. // resets the state variables etc (EndMode()))
  244. // Must call it before the SendDCN() because SendDCN causes
  245. // BG_CHKs if in strange state.
  246. iModemSyncEx(pTG, RESYNC_TIMEOUT1,0);
  247. if(pTG->T30.fReceivedDIS || pTG->T30.fReceivedDTC)
  248. {
  249. if(!SendDCN(pTG))
  250. {
  251. DebugPrintEx(DEBUG_ERR,"Could not send DCN");
  252. }
  253. }
  254. uRet = T30_CALLFAIL;
  255. goto done;
  256. NodeC:
  257. PSSLogEntry(PSS_MSG, 0, "Phase E - Hang-up");
  258. // +++ 4/12/95 Win95 hack -- to prevent ModemSync from sending
  259. // an AT here.
  260. iModemSyncEx(pTG, RESYNC_TIMEOUT1, fMDMSYNC_DCN);
  261. PSSLogEntry(PSS_MSG, 1, "Sending DCN");
  262. if(!SendDCN(pTG))
  263. {
  264. // We are the senders, so we should send DCN now.
  265. DebugPrintEx(DEBUG_ERR,"Could not send DCN");
  266. }
  267. // falls through here to receiving termination
  268. done:
  269. return uRet;
  270. }
  271. // End of T30 routine!!!!!!!!!
  272. ET30ACTION PhaseNodeA(PThrdGlbl pTG)
  273. {
  274. DEBUG_FUNCTION_NAME(_T("PhaseNodeA"));
  275. if(pTG->T30.ifrCommand == ifrDIS)
  276. {
  277. pTG->T30.fReceivedDIS = TRUE;
  278. }
  279. else if(pTG->T30.ifrCommand == ifrDTC)
  280. {
  281. pTG->T30.fReceivedDTC = TRUE;
  282. }
  283. return WhatNext(pTG, eventNODE_A, (WORD)pTG->T30.ifrCommand, 0, 0);
  284. }
  285. ET30ACTION PhaseNodeT(PThrdGlbl pTG)
  286. {
  287. DEBUG_FUNCTION_NAME(_T("PhaseNodeT"));
  288. /******** Transmitter Phase B. Fig A-7/T.30 (sheet 1) ********/
  289. // NodeT:
  290. // Have to redo this "DIS bit" everytime through PhaseB
  291. pTG->T30.fReceivedDIS = FALSE;
  292. // also the Received EOM stuff
  293. pTG->T30.fReceivedEOM = FALSE;
  294. // and teh received-DTC stuff
  295. pTG->T30.fReceivedDTC = FALSE;
  296. // INI file settings related stuff
  297. startTimeOut(pTG, &pTG->T30.toT1, T1_TIMEOUT);
  298. do
  299. {
  300. if(WhatNext(pTG, eventNODE_T, 0, 0, 0) == actionERROR)
  301. break;
  302. // no need for echo protection. We havnt transmitted anything!
  303. pTG->T30.ifrCommand = GetCommand(pTG, ifrPHASEBcommand);
  304. DebugPrintEx( DEBUG_MSG,
  305. "GetCommand returned %s",
  306. ifr_GetIfrDescription(pTG->T30.ifrCommand));
  307. switch(pTG->T30.ifrCommand)
  308. {
  309. // ifrTIMEOUT means no flags before T2
  310. // ifrNULL means timeout, or loss of carrier, or no flags
  311. // or no frame. ifrBAD means *only* bad frames recvd.
  312. case ifrBAD:
  313. case ifrTIMEOUT:
  314. case ifrNULL: break;
  315. case ifrCSI:
  316. case ifrNSF: if (!pTG->ProtInst.fRecvdDIS)
  317. {
  318. DebugPrintEx(DEBUG_WRN,"Ignoring NSF/CSI without DIS");
  319. break;
  320. }
  321. // if we're here the NSF-CSI-DIS was received in wrong
  322. // order (this is a violation of the T30 protocol
  323. // but we accept it anyway...
  324. // pretend it's a DIS
  325. pTG->T30.ifrCommand = ifrDIS;
  326. case ifrDIS:
  327. case ifrDTC: return actionGONODE_A; // got a valid frame
  328. case ifrDCN: DebugPrintEx( DEBUG_ERR, "Received DCN");
  329. return actionHANGUP;
  330. default: DebugPrintEx( DEBUG_ERR,
  331. "Caller T1: Got random ifr=%d",
  332. pTG->T30.ifrCommand);
  333. break; // continue with T1 loop
  334. }
  335. }
  336. while(checkTimeOut(pTG, &pTG->T30.toT1));
  337. PSSLogEntry(PSS_ERR, 1, "Failed to receive DIS - aborting");
  338. return actionHANGUP;
  339. }
  340. /*
  341. This node is transmitter side's TCF: Training Check Frame, known as 'phase B'.
  342. */
  343. ET30ACTION PhaseNodeD(PThrdGlbl pTG)
  344. {
  345. LPLPFR lplpfr;
  346. USHORT N;
  347. ET30ACTION action;
  348. USHORT uWhichDCS; // 0=first, 1=after NoReply 2=afterFTT
  349. DWORD TiffConvertThreadId;
  350. IFR lastResp; // The last respond from receiver
  351. /******** Transmitter Phase B2. Fig A-7/T.30 (sheet 1) ********/
  352. DEBUG_FUNCTION_NAME(_T("PhaseNodeD"));
  353. DebugPrintEx( DEBUG_MSG,
  354. "Now doing TCF, the last messages was: send=%d, receive=%d",
  355. pTG->T30.ifrSend,
  356. pTG->T30.ifrResp);
  357. // lets save the last received FSK, so we could know later that we have RTN in T30 Phase D (post page)
  358. // before this retrain phase (T30 Phase B)
  359. lastResp = pTG->T30.ifrResp;
  360. if (pTG->Inst.SendParams.Fax.Encoding == MR_DATA)
  361. {
  362. pTG->TiffConvertThreadParams.tiffCompression = TIFF_COMPRESSION_MR;
  363. }
  364. else
  365. {
  366. pTG->TiffConvertThreadParams.tiffCompression = TIFF_COMPRESSION_MH;
  367. }
  368. if (pTG->Inst.SendParams.Fax.AwRes & ( AWRES_mm080_077 | AWRES_200_200 ) )
  369. {
  370. pTG->TiffConvertThreadParams.HiRes = 1;
  371. }
  372. else
  373. {
  374. pTG->TiffConvertThreadParams.HiRes = 0;
  375. }
  376. _fmemcpy (pTG->TiffConvertThreadParams.lpszLineID, pTG->lpszPermanentLineID, 8);
  377. pTG->TiffConvertThreadParams.lpszLineID[8] = 0;
  378. uWhichDCS = 0;
  379. NodeD:
  380. N = 0;
  381. lplpfr = 0;
  382. action = WhatNext( pTG,
  383. eventSENDDCS,
  384. (WORD)uWhichDCS,
  385. (ULONG_PTR)((LPUWORD)&N),
  386. (ULONG_PTR)((LPLPLPFR)&lplpfr));
  387. switch(action)
  388. {
  389. case actionDCN: DebugPrintEx( DEBUG_ERR,
  390. "Got actionDCN from eventSENDDCS(uWhichDCS=%d)",
  391. uWhichDCS);
  392. // This means that we can't drop the speed any further
  393. PSSLogEntry(PSS_ERR, 1, "Failed to train at lowest speed - aborting");
  394. pTG->fFatalErrorWasSignaled = TRUE;
  395. SignalStatusChangeWithStringId(pTG, FS_SEND_BAD_TRAINING, IDS_SEND_BAD_TRAINING);
  396. return actionDCN;
  397. case actionSENDDCSTCF: break;
  398. case actionSKIPTCF: break; // Ricoh hook
  399. case actionERROR: return action; // goto PhaseLoop & exit
  400. default: return actionERROR;
  401. }
  402. NodeDprime: // used only by TCF--no reply
  403. // The WhatNext function check for User-Abort, in NodeD we call this function and now we don't have to
  404. // So we check here for hangup as WhatNext do and return actionERROR in case there was an User Abrot request
  405. if (pTG->fAbortRequested)
  406. {
  407. if (pTG->fOkToResetAbortReqEvent && (!pTG->fAbortReqEventWasReset))
  408. {
  409. DebugPrintEx( DEBUG_MSG,
  410. "(D-Prime)found that there was an Abort."
  411. " RESETTING AbortReqEvent");
  412. pTG->fAbortReqEventWasReset = TRUE;
  413. if (!ResetEvent(pTG->AbortReqEvent))
  414. {
  415. DebugPrintEx( DEBUG_ERR,
  416. "ResetEvent(0x%lx) returns failure code: %ld",
  417. (ULONG_PTR)pTG->AbortReqEvent,
  418. (long) GetLastError());
  419. }
  420. }
  421. DebugPrintEx(DEBUG_MSG,"ABORTing");
  422. return actionERROR;
  423. }
  424. PSSLogEntry(PSS_MSG, 1, "Sending TSI-DCS");
  425. // Check for the returned value, Maybe the receiver hang-up
  426. if (!SendManyFrames(pTG, lplpfr, N))
  427. {
  428. // The function print debug information
  429. // What else shall we do??
  430. PSSLogEntry(PSS_ERR, 1, "Failed to send TSI-DCS - aborting");
  431. return actionDCN;
  432. }
  433. if(action != actionSKIPTCF) // Ricoh hook
  434. {
  435. if (!pTG->fTiffThreadCreated)
  436. {
  437. DebugPrintEx(DEBUG_MSG,"Creating TIFF helper thread");
  438. pTG->hThread = CreateThread(
  439. NULL,
  440. 0,
  441. (LPTHREAD_START_ROUTINE) TiffConvertThread,
  442. (LPVOID) pTG,
  443. 0,
  444. &TiffConvertThreadId
  445. );
  446. if (!pTG->hThread)
  447. {
  448. DebugPrintEx(DEBUG_ERR,"TiffConvertThread create FAILED");
  449. return actionDCN;
  450. }
  451. pTG->fTiffThreadCreated = TRUE;
  452. pTG->AckTerminate = FALSE;
  453. pTG->fOkToResetAbortReqEvent = FALSE;
  454. if ( (pTG->RecoveryIndex >=0 ) && (pTG->RecoveryIndex < MAX_T30_CONNECT) )
  455. {
  456. T30Recovery[pTG->RecoveryIndex].TiffThreadId = TiffConvertThreadId;
  457. T30Recovery[pTG->RecoveryIndex].CkSum = ComputeCheckSum(
  458. (LPDWORD) &T30Recovery[pTG->RecoveryIndex].fAvail,
  459. sizeof ( T30_RECOVERY_GLOB ) / sizeof (DWORD) - 1 );
  460. }
  461. }
  462. PSSLogEntry(PSS_MSG, 1, "Sending TCF...");
  463. if (!SendTCF(pTG))
  464. {
  465. PSSLogEntry(PSS_ERR, 1, "Failed to send TCF - aborting");
  466. return actionDCN;
  467. }
  468. pTG->T30.uTrainCount++;
  469. PSSLogEntry(PSS_MSG, 1, "Successfully sent TCF");
  470. }
  471. // no need for echo protection? Wouldnt know what to do anyway!
  472. pTG->T30.ifrResp = GetResponse(pTG, ifrTCFresponse);
  473. // Before this switch check if there was an abort!!!
  474. switch(pTG->T30.ifrResp)
  475. {
  476. case ifrDCN: PSSLogEntry(PSS_ERR, 1, "Recevied DCN - hanging up");
  477. return actionHANGUP; // got DCN. Must hangup
  478. case ifrBAD: // ifrBAD means *only* bad frames recvd. Treat like NULL
  479. case ifrNULL: // timeout. May try again
  480. if(pTG->T30.uTrainCount >= 3)
  481. {
  482. PSSLogEntry(PSS_ERR, 1, "Failed to receive response from TCF 3 times - aborting");
  483. pTG->fFatalErrorWasSignaled = TRUE;
  484. SignalStatusChangeWithStringId(pTG, FS_NO_RESPONSE, IDS_NO_RESPONSE);
  485. return actionDCN; // Maybe we should return here actionHANGUP
  486. }
  487. else
  488. {
  489. PSSLogEntry(PSS_WRN, 1, "Failed to receive response from TCF - sending TSI-DCS again");
  490. uWhichDCS = 1;
  491. // goto NodeD; // send new DCS??
  492. goto NodeDprime; // resend *same* DCS, same baudrate
  493. }
  494. case ifrDIS:
  495. case ifrDTC: if(pTG->T30.uTrainCount >= 3)
  496. {
  497. DebugPrintEx(DEBUG_ERR,"Got DIS/DTC after 3 TCFs");
  498. return actionDCN;
  499. }
  500. else
  501. {
  502. pTG->T30.ifrCommand = pTG->T30.ifrResp;
  503. return actionGONODE_A;
  504. }
  505. case ifrFTT:
  506. // reset training count on FTT since we drop speed. Want to try
  507. // 3 times _without_ a response (DIS DTC doesn't count) before
  508. // giving up
  509. PSSLogEntry(PSS_WRN, 1, "Received FTT - renegotiating");
  510. pTG->T30.uTrainCount = 0;
  511. uWhichDCS = 2;
  512. goto NodeD;
  513. case ifrCFR: // This is the normal respond
  514. pTG->T30.uTrainCount = 0;
  515. PSSLogEntry(PSS_MSG, 1, "Received CFR");
  516. switch(action = WhatNext(pTG, eventGOTCFR, 0, 0, 0))
  517. {
  518. case actionGONODE_I: // Non-ECM PhaseC
  519. DebugPrintEx( DEBUG_MSG,
  520. "T30 PhaseB: Got CFR, Non-ECM PhaseC");
  521. {
  522. // This is an Hack. Now we got CFR, we should start transmitting the last page again
  523. // We put back the RTN to 'ifrResp' so that T30 PhaseC will know to send the same page.
  524. if (lastResp == ifrRTN)
  525. {
  526. pTG->T30.ifrResp = ifrRTN;
  527. }
  528. return action;
  529. }
  530. case actionGONODE_D:
  531. goto NodeD; // Ricoh hook
  532. case actionERROR:
  533. return action; // goto PhaseLoop & exit
  534. default:
  535. return actionERROR;
  536. }
  537. default:
  538. {
  539. DebugPrintEx(DEBUG_ERR,"Unknown Reply to TCF");
  540. return actionDCN;
  541. }
  542. }
  543. }
  544. ET30ACTION NonECMPhaseC(PThrdGlbl pTG)
  545. {
  546. /******** Transmitter Phase C. Fig A-7/T.30 (sheet 1) ********/
  547. LPBUFFER lpbf=0;
  548. ULONG lTotalLen=0;
  549. SWORD swRet;
  550. USHORT uMod, uEnc;
  551. DEBUG_FUNCTION_NAME(("NonECMPhaseC"));
  552. PSSLogEntry(PSS_MSG, 0, "Phase C - Page transmission");
  553. // Callback to open file to send. Returns no data
  554. if((swRet=ICommGetSendBuf(pTG, 0, SEND_STARTPAGE)) != SEND_OK)
  555. {
  556. DebugPrintEx( DEBUG_ERR,
  557. "Nonzero return %d from SendProc at Start Page",
  558. swRet);
  559. // return actionDCN;
  560. return actionERROR;
  561. }
  562. DebugPrintEx(DEBUG_MSG, "Got Startpage in T30");
  563. uEnc = pTG->ProtInst.SendParams.Fax.Encoding;
  564. uMod = pTG->ProtInst.llNegot.Baud;
  565. // in non-ECM mode, PhaseC is ALWAYS with short-train.
  566. // Only TCF uses long-train
  567. if(uMod >= V17_START) uMod |= ST_FLAG;
  568. // **MUST** call RecvSilence here since it is recv-followed-by-send case
  569. // here we should use a small timeout (100ms?) and if it fails,
  570. // should go back to sending the previous V21 frame (which could be DCS
  571. // or MPS or whatever, which is why it gets complicated & we havn't
  572. // done it!). Meanwhile use a long timeout, ignore return value
  573. // and send anyway.
  574. Sleep(RECV_PHASEC_PAUSE);
  575. if(!ModemSendMode(pTG, uMod))
  576. {
  577. DebugPrintEx( DEBUG_ERR,
  578. "ModemSendMode failed in Tx PhaseC");
  579. return actionERROR;
  580. }
  581. // need to send these quickly to avoid underrun (see bug842).
  582. // Also move the preamble/postamble into the ModemSendMode
  583. // and ModemSendMem(FINAL)
  584. // Already sent (in ModemSendMode)
  585. // SendZeros(PAGE_PREAMBLE, FALSE); // Send some zeros to warm up....
  586. // need to set line min zeros here. get from prot and call Modem
  587. // Enable ZERO stuffing
  588. FComSetStuffZERO(pTG,
  589. MinScanToBytesPerLine(pTG, pTG->ProtInst.llNegot.MinScan, pTG->ProtInst.llNegot.Baud));
  590. // DONT SEND an EOL here. See BUG#6441. We now make sure the EOL is
  591. // added by FAXCODEC. At this level we only append the RTC
  592. PSSLogEntry(PSS_MSG, 1, "Sending page %d data...", pTG->PageCount);
  593. lTotalLen = 0;
  594. while((swRet=ICommGetSendBuf(pTG, &lpbf, SEND_SEQ)) == SEND_OK)
  595. {
  596. if(!lpbf->wLengthData)
  597. {
  598. DebugPrintEx(DEBUG_ERR,"Got 0 bytes from GetSendBuf--freeing buf");
  599. MyFreeBuf(pTG, lpbf);
  600. continue;
  601. }
  602. lTotalLen += lpbf->wLengthData;
  603. if(!ModemSendMem(pTG, lpbf->lpbBegData, lpbf->wLengthData, 0))
  604. {
  605. PSSLogEntry(PSS_ERR, 1, "Failed to send page data - aborting");
  606. return actionERROR; // goto error;
  607. }
  608. if(!MyFreeBuf(pTG, lpbf))
  609. {
  610. DebugPrintEx(DEBUG_ERR,"FReeBuf failed in NON-ECM Phase C");
  611. return actionERROR; // goto error;
  612. }
  613. lpbf = 0;
  614. }
  615. PSSLogEntry(PSS_MSG, 2, "send: page data, %d bytes", lTotalLen);
  616. if(swRet == SEND_ERROR)
  617. {
  618. PSSLogEntry(PSS_ERR, 1, "Failed to send page data - aborting");
  619. // return actionDCN;
  620. return actionERROR;
  621. }
  622. PSSLogEntry(PSS_MSG, 1, "Successfully sent page data - sending RTC");
  623. FComSetStuffZERO(pTG, 0); // Disable ZERO stuffing BEFORE sending RTC!
  624. if(!SendRTC(pTG, FALSE)) // RTC and final flag NOT set
  625. {
  626. PSSLogEntry(PSS_ERR, 1, "Failed to send RTC - aborting");
  627. return actionERROR; // error return from ModemSendMem
  628. }
  629. PSSLogEntry(PSS_MSG, 1, "Successfully sent RTC");
  630. // Send zeros to cool off FINAL flag SET
  631. SendZeros(pTG, (USHORT)(TCFLen[uMod & 0x0F] / (PAGE_POSTAMBLE_DIV)), TRUE);
  632. DebugPrintEx( DEBUG_MSG,
  633. "Page Send Done.....len=(%ld, 0x%08x)",
  634. lTotalLen,
  635. lTotalLen);
  636. return actionGONODE_II;
  637. }
  638. ET30ACTION NonECMPhaseD(PThrdGlbl pTG)
  639. {
  640. USHORT uTryCount;
  641. ET30ACTION action;
  642. /******** Transmitter Phase D. Fig A-7/T.30 (sheet 2) ********/
  643. // NodeII:
  644. DEBUG_FUNCTION_NAME(_T("NonECMPhaseD"));
  645. PSSLogEntry(PSS_MSG, 0, "Phase D - Post message exchange");
  646. switch(action = WhatNext(pTG, eventPOSTPAGE, 0, 0, 0))
  647. {
  648. case actionSENDMPS: pTG->T30.ifrSend = ifrMPS;
  649. break;
  650. case actionSENDEOM: pTG->T30.ifrSend = ifrEOM;
  651. break;
  652. case actionSENDEOP: pTG->T30.ifrSend = ifrEOP;
  653. break;
  654. case actionERROR: return action; // goto PhaseLoop & exit
  655. default: return actionERROR;
  656. }
  657. for(uTryCount=0;;)
  658. {
  659. DebugPrintEx( DEBUG_MSG,
  660. "Sending postpage #=%d in T30",
  661. pTG->T30.ifrSend);
  662. PSSLogEntry(PSS_MSG, 1, "Sending %s", rgFrameInfo[pTG->T30.ifrSend].szName);
  663. // RSL dont sleep here
  664. SendSingleFrame(pTG, pTG->T30.ifrSend, 0, 0, 0);
  665. echoretry:
  666. pTG->T30.ifrResp = GetResponse(pTG, ifrPOSTPAGEresponse);
  667. // if we hear our own frame, try to recv again. DONT retransmit!
  668. if(pTG->T30.ifrResp==pTG->T30.ifrSend)
  669. {
  670. DebugPrintEx( DEBUG_WRN,
  671. "Ignoring ECHO of %s(%d)",
  672. (LPSTR)(rgFrameInfo[pTG->T30.ifrResp].szName),
  673. pTG->T30.ifrResp);
  674. goto echoretry;
  675. }
  676. DebugPrintEx( DEBUG_MSG,
  677. "Got postpage resp #=%d in T30",
  678. pTG->T30.ifrResp);
  679. if(pTG->T30.ifrResp != ifrNULL && pTG->T30.ifrResp != ifrBAD)
  680. break;
  681. if(++uTryCount >= 3)
  682. {
  683. PSSLogEntry(PSS_ERR, 1, "Received no response after 3 attempts - aborting");
  684. pTG->fFatalErrorWasSignaled = TRUE;
  685. SignalStatusChangeWithStringId(pTG, FS_NO_RESPONSE, IDS_NO_RESPONSE);
  686. return actionDCN;
  687. }
  688. PSSLogEntry(PSS_WRN, 1, "Received no response - retrying");
  689. }
  690. PSSLogEntry(PSS_MSG, 1, "Received %s", rgFrameInfo[pTG->T30.ifrResp].szName);
  691. switch(pTG->T30.ifrResp)
  692. {
  693. case ifrBAD: // ifrBAD means *only* bad frames recvd. Treat like NULL
  694. case ifrNULL: return actionERROR; // in case they do
  695. case ifrDCN: DebugPrintEx( DEBUG_ERR,
  696. "Got ifrDCN from GetResponse after sending post-page command");
  697. return actionHANGUP;
  698. case ifrPIN:
  699. case ifrPIP:
  700. DebugPrintEx(DEBUG_WRN,"Procedure interrupts not supported");
  701. pTG->T30.ifrResp = pTG->T30.ifrResp - ifrPIP + ifrRTP;
  702. // return actionERROR;
  703. // return actionDCN;
  704. // default: // fallthrough --- MCF, RTN, RTP
  705. }
  706. action = WhatNext( pTG,
  707. eventGOTPOSTPAGERESP,
  708. (WORD)pTG->T30.ifrResp,
  709. (DWORD)pTG->T30.ifrSend,
  710. 0);
  711. if ( pTG->T30.ifrSend==ifrEOP &&
  712. (pTG->T30.ifrResp==ifrMCF || pTG->T30.ifrResp==ifrRTP)
  713. && action==actionDCN )
  714. {
  715. return actionDCN_SUCCESS;
  716. }
  717. else
  718. {
  719. return action;
  720. }
  721. }
  722. #define SKIP_TCF_TIME 1500
  723. ET30ACTION RecvPhaseB(PThrdGlbl pTG, ET30ACTION action)
  724. {
  725. LPLPFR lplpfr;
  726. USHORT N, i;
  727. /******** Receiver Phase B. Fig A-7/T.30 (sheet 1) ********/
  728. DEBUG_FUNCTION_NAME(_T("RecvPhaseB"));
  729. DebugPrintEx( DEBUG_MSG,
  730. "T30: The last command from transmitter was ifrCommand=%d",
  731. pTG->T30.ifrCommand);
  732. if(action == actionGONODE_R1)
  733. {
  734. // NodeR1:
  735. // Have to redo this "DIS bit" everytime through PhaseB
  736. pTG->T30.fReceivedDIS = FALSE; // set to FALSE when sending DIS
  737. // also the Received EOM stuff
  738. pTG->T30.fReceivedEOM = FALSE;
  739. // and teh received-DTC stuff
  740. pTG->T30.fReceivedDTC = FALSE;
  741. N = 0;
  742. lplpfr = 0;
  743. action = WhatNext( pTG,
  744. eventSENDDIS,
  745. (WORD)0,
  746. (ULONG_PTR)((LPUWORD)&N),
  747. (ULONG_PTR)((LPLPLPFR)&lplpfr));
  748. }
  749. switch(action)
  750. {
  751. case actionDCN: DebugPrintEx( DEBUG_ERR,
  752. "Got actionDCN from eventSENDDIS or SENDDTC");
  753. return actionDCN;
  754. case actionSEND_DIS:
  755. case actionSEND_DTC: break;
  756. case actionERROR: return action; // goto PhaseLoop & exit
  757. default: return actionERROR;
  758. }
  759. startTimeOut(pTG, &pTG->T30.toT1, T1_TIMEOUT);
  760. do // Until time-out, or an error occured
  761. {
  762. // do nothing. Hook for abort in T1 loop
  763. if(WhatNext(pTG, eventNODE_R, 0, 0, 0) == actionERROR)
  764. break;
  765. // The receiving speed is unknown now:
  766. pTG->T30.uRecvTCFMod = 0xFFFF;
  767. PSSLogEntry(PSS_MSG, 1, "Sending CSI-DIS");
  768. if (!SendManyFrames(pTG, lplpfr, N))
  769. {
  770. // We want to know about failure here.
  771. PSSLogEntry(PSS_ERR, 1, "Failed to send CSI-DIS");
  772. }
  773. else
  774. {
  775. PSSLogEntry(PSS_MSG, 1, "Successfully sent CSI-DIS - receiving response");
  776. }
  777. echoretry:
  778. DebugPrintEx(DEBUG_MSG,"Getting Response");
  779. // Here we get the response for the NSF or DIS we send, or after EOM
  780. // There is no check for the validity of the returned frame
  781. pTG->T30.ifrCommand=GetResponse(pTG, ifrPHASEBresponse);
  782. DebugPrintEx( DEBUG_MSG,
  783. "GetResponse returned %s",
  784. ifr_GetIfrDescription(pTG->T30.ifrCommand));
  785. // if we hear our own frame, try to recv again. DONT retransmit!
  786. for(i=0; i<N; i++) // Notice that N=0 after EOM, so we skip this check
  787. {
  788. if(pTG->T30.ifrCommand == lplpfr[i]->ifr)
  789. {
  790. DebugPrintEx( DEBUG_WRN,
  791. "Ignoring ECHO of %s(%d)",
  792. (LPSTR)(rgFrameInfo[pTG->T30.ifrCommand].szName),
  793. pTG->T30.ifrCommand);
  794. goto echoretry;
  795. }
  796. }
  797. // We decide what to do by checking the last received frame
  798. switch(pTG->T30.ifrCommand)
  799. {
  800. case ifrEOM: // The last page was followed by EOM. The sender did not "hear" our MCF
  801. if (!SendMCF(pTG))
  802. {
  803. DebugPrintEx(DEBUG_ERR,"Failed to SendMCF");
  804. }
  805. break;
  806. case ifrNSS: // do same as for DCS
  807. case ifrDCS: // If there are many frames and one of them is DCS, then pTG->T30.ifrCommand contains DCS
  808. // This function will return if there was no DCS yet (the receive modiulation is not known)
  809. return PhaseGetTCF(pTG, pTG->T30.ifrCommand);
  810. case ifrBAD: // ifrBAD means *only* bad frames recvd. Treat like NULL
  811. case ifrNULL: // we expect to get a DCS in phase B
  812. // which means the sender will follow it by a TCF
  813. // the sender doesn't know we failed to get the DCS
  814. // so the TCF will follow anyway
  815. // we have to wait before re-sending NSF-DIS
  816. // or we'll collide with TCF
  817. Sleep(SKIP_TCF_TIME);
  818. break; // out of the switch() and continue with loop
  819. case ifrDCN:
  820. DebugPrintEx(DEBUG_ERR,"Got DCN after DIS or DTC");
  821. return actionHANGUP; //bugfix #478
  822. default:
  823. return actionGONODE_RECVCMD;
  824. }
  825. }
  826. while(checkTimeOut(pTG, &(pTG->T30.toT1)));
  827. DebugPrintEx(DEBUG_ERR,"T1 timeout on Receiver");
  828. if (pTG->fReceivedHDLCflags)
  829. {
  830. PSSLogEntry(PSS_ERR, 1, "Didn't receive any response from sender");
  831. pTG->fFatalErrorWasSignaled = TRUE;
  832. SignalStatusChangeWithStringId(pTG, FS_NO_RESPONSE, IDS_NO_RESPONSE);
  833. }
  834. else
  835. {
  836. PSSLogEntry(PSS_ERR, 1, "Didn't receive any response from sender - this call was not a fax call");
  837. pTG->fFatalErrorWasSignaled = TRUE;
  838. SignalStatusChangeWithStringId(pTG, FS_RECV_NOT_FAX_CALL, IDS_RECV_NOT_FAX_CALL);
  839. }
  840. return actionDCN;
  841. }
  842. ET30ACTION PhaseNodeF(PThrdGlbl pTG, BOOL fEopMcf)
  843. {
  844. USHORT uFLoopCount;
  845. BOOL fSentFTT = pTG->fSentFTT;
  846. DEBUG_FUNCTION_NAME(_T("PhaseNodeF"));
  847. pTG->fSentFTT = FALSE;
  848. // NodeF:
  849. uFLoopCount = 0;
  850. for(;;)
  851. {
  852. pTG->T30.uRecvTCFMod = 0xFFFF; // This mark that we don't know yet the rate (no DCS, yet)
  853. echoretry:
  854. pTG->T30.ifrCommand = GetCommand(pTG, (USHORT)(pTG->EchoProtect.fGotWrongMode ? ifrNODEFafterWRONGMODE : ifrNODEFcommand));
  855. // reset the fGotWrongMode flag
  856. pTG->EchoProtect.fGotWrongMode = 0;
  857. // if we hear the last frame we sent, try to recv again. DONT retx!
  858. // bug--might have matched ifrNULL...
  859. // added: if ModemRecvMode() returns EOF then also retry. RecvMode
  860. // returns RECV_EOF only if we pass it the ifrNODEFafterWRONGMODE hint
  861. // and it senses silence (i.e. we saw a V21 echo but missed it). In
  862. // this case we want to retry the high speed PIX recv
  863. if(pTG->EchoProtect.ifrLastSent && (pTG->T30.ifrCommand==pTG->EchoProtect.ifrLastSent || pTG->T30.ifrCommand==ifrEOFfromRECVMODE))
  864. {
  865. DebugPrintEx( DEBUG_WRN,
  866. "Ignoring ECHO of %s(%d)",
  867. (LPSTR)(rgFrameInfo[pTG->T30.ifrCommand].szName),
  868. pTG->T30.ifrCommand);
  869. switch(pTG->EchoProtect.modePrevRecv)
  870. {
  871. default:
  872. case modeNONE: goto echoretry;
  873. case modeNONECM: return actionGONODE_RECVPHASEC;
  874. }
  875. }
  876. // as soon as we get anything else ZERO the pTG->EchoProtect state
  877. _fmemset(&pTG->EchoProtect, 0, sizeof(pTG->EchoProtect));
  878. switch(pTG->T30.ifrCommand)
  879. {
  880. // ifrNULL means T2 timeout, or loss of carrier, or no flags
  881. // or no frame. ifrBAD means *only* bad frame(s) recvd.
  882. case ifrNSS: // do same as for DCS
  883. case ifrDCS: return PhaseGetTCF(pTG, pTG->T30.ifrCommand);
  884. // ifrDCS is highly time-critical!!
  885. case ifrBAD:
  886. case ifrNULL: break; // Loop again, until timeout
  887. case ifrTIMEOUT: goto T2Timeout;
  888. // ifrTIMEOUT means T2 timed out without flags...
  889. case ifrDCN: if(fEopMcf)
  890. {
  891. PSSLogEntry(PSS_MSG, 1, "Received DCN");
  892. return actionHANGUP_SUCCESS;
  893. }
  894. else
  895. {
  896. if (fSentFTT)
  897. {
  898. // Last thing we sent was FTT - sender must've given up
  899. PSSLogEntry(PSS_ERR, 1, "Received DCN after FTT");
  900. pTG->fFatalErrorWasSignaled = TRUE;
  901. SignalStatusChangeWithStringId(pTG, FS_RECV_BAD_TRAINING, IDS_RECV_BAD_TRAINING);
  902. }
  903. else
  904. {
  905. PSSLogEntry(PSS_ERR, 1, "Received DCN unexpectedly");
  906. }
  907. return actionHANGUP;
  908. }
  909. default: return actionGONODE_RECVCMD;
  910. }
  911. }
  912. T2Timeout:
  913. DebugPrintEx(DEBUG_WRN,"T2 timed out");
  914. // restart PhaseB after T2 timeout IFF (a) EOM or PPS-EOM was recvd
  915. // AND (b) If we are in ECM mode, the last response sent was n MCF
  916. // This avoids us doing this after sending a CTR, RNR or PPR
  917. // Ricoh's protocol conformance tester doesnt like this. This is
  918. // Ricoh's bug numbbers B3-0142, 0143, 0144
  919. if(pTG->T30.fReceivedEOM)
  920. {
  921. return actionGONODE_R1;
  922. }
  923. if(fEopMcf)
  924. {
  925. PSSLogEntry(PSS_WRN, 1, "Failed to receive DCN - will be considered as success");
  926. return actionHANGUP_SUCCESS;
  927. }
  928. else
  929. {
  930. PSSLogEntry(PSS_ERR, 1, "Failed to receive command - aborting");
  931. pTG->fFatalErrorWasSignaled = TRUE;
  932. SignalStatusChangeWithStringId(pTG, FS_NO_RESPONSE, IDS_NO_RESPONSE);
  933. return actionHANGUP;
  934. }
  935. }
  936. ET30ACTION PhaseRecvCmd(PThrdGlbl pTG)
  937. {
  938. ET30ACTION action;
  939. DEBUG_FUNCTION_NAME(_T("PhaseRecvCmd"));
  940. if(pTG->T30.ifrCommand == ifrDCN)
  941. {
  942. DebugPrintEx(DEBUG_ERR,"Got DCN in GetCommand");
  943. return actionHANGUP;
  944. }
  945. if( pTG->T30.ifrCommand==ifrDTC || pTG->T30.ifrCommand==ifrDCS ||
  946. pTG->T30.ifrCommand==ifrDIS || pTG->T30.ifrCommand==ifrNSS)
  947. {
  948. switch(action = WhatNext( pTG,
  949. eventRECVCMD,
  950. (WORD)pTG->T30.ifrCommand,
  951. 0,
  952. 0))
  953. {
  954. case actionGETTCF: DebugPrintEx(DEBUG_ERR,"MainBody: Wrong Way to GETTCF");
  955. return actionERROR;
  956. case actionGONODE_A: return actionGONODE_A;
  957. // NTRAID#EDGEBUGS-9691-2000/07/24-moolyb - this is never executed
  958. case actionGONODE_D: return action;
  959. // end this is never executed
  960. case actionHANGUP: DebugPrintEx(DEBUG_ERR,"Got actionHANGUP from eventRECVCMD");
  961. return action;
  962. case actionERROR: return action; // goto PhaseLoop & exit
  963. default: return actionERROR;
  964. }
  965. }
  966. if( pTG->T30.ifrCommand == ifrEOM ||
  967. pTG->T30.ifrCommand == ifrPRI_EOM ||
  968. pTG->T30.ifrCommand == ifrPPS_EOM ||
  969. pTG->T30.ifrCommand == ifrPPS_PRI_EOM ||
  970. pTG->T30.ifrCommand == ifrEOR_EOM ||
  971. pTG->T30.ifrCommand == ifrEOR_PRI_EOM )
  972. {
  973. pTG->T30.fReceivedEOM = TRUE;
  974. }
  975. else if(pTG->T30.ifrCommand >= ifrPRI_FIRST && pTG->T30.ifrCommand <= ifrPRI_LAST)
  976. {
  977. pTG->T30.ifrCommand = pTG->T30.ifrCommand-ifrPRI_MPS+ifrMPS;
  978. // fall thru to GONODEIII
  979. }
  980. if(pTG->T30.ifrCommand >= ifrMPS && pTG->T30.ifrCommand <= ifrEOP) // in {MPS, EOM, EOP}
  981. {
  982. PSSLogEntry(PSS_MSG, 1, "Received %s", rgFrameInfo[pTG->T30.ifrCommand].szName);
  983. return actionGONODE_III;
  984. }
  985. else
  986. {
  987. DebugPrintEx(DEBUG_ERR,"Got UNKNOWN in GetCommand");
  988. return actionHANGUP;
  989. }
  990. }
  991. // We are here after we got the DCS (Digital Command Signal)
  992. // Now, we suppose to get TCF. After that we should do some checking on the DCS parameters (eg.: PageWidth...)
  993. // According to the protocol after the DCS we must get the TCF,
  994. // and just after that we can say that the parameters were bad (FTT) are good (CFR)
  995. extern BYTE T30toC1[16];
  996. ET30ACTION PhaseGetTCF(PThrdGlbl pTG, IFR ifr)
  997. {
  998. SWORD swRet;
  999. IFR ifrDummy;
  1000. ET30ACTION action;
  1001. DEBUG_FUNCTION_NAME(_T("PhaseGetTCF"));
  1002. if (pTG->T30.uRecvTCFMod == 0xFFFF) // uninitialised
  1003. {
  1004. ECHOPROTECT(0, 0);
  1005. CLEAR_MISSED_TCFS();
  1006. action = actionGONODE_F;
  1007. goto error;
  1008. }
  1009. if (T30toC1[pTG->T30.uRecvTCFMod & 0xF] == 0) // invalid
  1010. {
  1011. PSSLogEntry(PSS_ERR, 1, "DCS specified invalid modulation - disconnecting");
  1012. action = actionDCN;
  1013. goto error;
  1014. }
  1015. PSSLogEntry(PSS_MSG, 1, "Receiving TCF...");
  1016. swRet = GetTCF(pTG); // swRet = errs per 1000, +ve or 0 if we think its good
  1017. // -ve if we think its bad. -1111 if other error
  1018. // -1000 if too short
  1019. if(swRet < -1000)
  1020. {
  1021. ECHOPROTECT(0, 0);
  1022. pTG->T30.uMissedTCFs++;
  1023. if (pTG->T30.uMissedTCFs >= MAX_MISSED_TCFS_BEFORE_FTT)
  1024. {
  1025. PSSLogEntry(PSS_WRN, 1, "Failed to receive TCF %u times - will be considered as bad TCF",
  1026. (unsigned) pTG->T30.uMissedTCFs);
  1027. CLEAR_MISSED_TCFS();
  1028. swRet = -1000; // We pretend we got a too-short TCF.
  1029. }
  1030. else
  1031. {
  1032. PSSLogEntry(PSS_WRN, 1, "Failed to receive TCF - receiving commands");
  1033. action = actionGONODE_F;
  1034. goto error;
  1035. }
  1036. }
  1037. // Here we can also signal the frames received before DCS!
  1038. // Were no longer in time-critical mode, so call all the
  1039. // callbacks we skipped. One for recording the received frames
  1040. // and one for handling teh received command, i.e. DCS.
  1041. // (the only options the protocol has is actionGETTCF or HANGUP)
  1042. ifrDummy = ifr;
  1043. // When we calling to WhatNext with eventGOTFRAMES, the DCS will be copied to pTG->ProtInst->RemoteDCS
  1044. //
  1045. action = WhatNext( pTG,
  1046. eventGOTFRAMES,
  1047. pTG->T30.Nframes,
  1048. (ULONG_PTR)((LPLPFR)(pTG->T30.lpfs->rglpfr)),
  1049. (ULONG_PTR)((LPIFR)(&ifrDummy)));
  1050. if (action==actionERROR)
  1051. {
  1052. goto error;
  1053. }
  1054. if(ifr != ifrDummy)
  1055. {
  1056. switch(ifrDummy)
  1057. {
  1058. case ifrNULL:
  1059. case ifrBAD:
  1060. DebugPrintEx(DEBUG_ERR,"Got ifrBAD from whatnext after recv TCF");
  1061. ECHOPROTECT(0, 0);
  1062. CLEAR_MISSED_TCFS();
  1063. action = actionGONODE_F;
  1064. goto error;
  1065. default:
  1066. break;
  1067. }
  1068. }
  1069. // Now call teh callback to check the received TCF and
  1070. // return either FTT or CFR
  1071. switch(action = WhatNext(pTG, eventGOTTCF,(WORD)swRet, 0, 0))
  1072. {
  1073. case actionSENDCFR:
  1074. PSSLogEntry(PSS_MSG, 1, "Received good TCF - sending CFR");
  1075. if (!SendCFR(pTG))
  1076. {
  1077. PSSLogEntry(PSS_WRN, 1, "Failed to send CFR - receiving commands");
  1078. return actionGONODE_F;
  1079. }
  1080. // after sending CFR we are again in a race
  1081. ECHOPROTECT(ifrCFR, 0); // dunno recv mode yet
  1082. PSSLogEntry(PSS_MSG, 1, "Successfully sent CFR");
  1083. return actionGONODE_RECVPHASEC;
  1084. case actionSENDFTT:
  1085. // PSSLogEntry(PSS_WRN, 1, "Received bad TCF - sending FTT"); // Done inside WhatNext(eventGOTTCF)
  1086. if (!SendFTT(pTG))
  1087. {
  1088. PSSLogEntry(PSS_WRN, 1, "Failed to send FTT - receiving commands");
  1089. }
  1090. else
  1091. {
  1092. PSSLogEntry(PSS_MSG, 1, "Successfully sent FTT - receiving commands");
  1093. ECHOPROTECT(ifrFTT, 0);
  1094. pTG->fSentFTT = TRUE;
  1095. }
  1096. CLEAR_MISSED_TCFS();
  1097. return actionGONODE_F;
  1098. case actionERROR:
  1099. goto error;
  1100. default:
  1101. action = actionERROR;
  1102. goto error;
  1103. }
  1104. error:
  1105. // missed TCF or no NSS. Did _not_ reply to TCF
  1106. // if we sent a reply, must _not_ come here
  1107. return action;
  1108. }
  1109. ET30ACTION NonECMRecvPhaseC(PThrdGlbl pTG)
  1110. {
  1111. /******** Receiver Phase C. Fig A-7/T.30 (sheet 1) ********/
  1112. LPBUFFER lpbf;
  1113. ULONG lTotalLen=0;
  1114. USHORT uRet, uMod, uEnc;
  1115. DWORD tiffCompression;
  1116. DWORD HiRes;
  1117. // There is a race between sending the CFR and sending out an
  1118. // +FRM=xx command, so we want to do it ASAP.
  1119. DEBUG_FUNCTION_NAME(_T("NonECMRecvPhaseC"));
  1120. PSSLogEntry(PSS_MSG, 0, "Phase C - Receive page");
  1121. pTG->T30.fReceivedPage = FALSE; // Right now, there's no page...
  1122. uEnc = pTG->ProtInst.RecvParams.Fax.Encoding;
  1123. if (uEnc == MR_DATA)
  1124. {
  1125. tiffCompression = TIFF_COMPRESSION_MR;
  1126. }
  1127. else
  1128. {
  1129. tiffCompression = TIFF_COMPRESSION_MH;
  1130. }
  1131. if (pTG->ProtInst.RecvParams.Fax.AwRes & (AWRES_mm080_077 | AWRES_200_200) )
  1132. {
  1133. HiRes = 1;
  1134. }
  1135. else
  1136. {
  1137. HiRes = 0;
  1138. }
  1139. //
  1140. // do it once per RX
  1141. //
  1142. if ( !pTG->fTiffOpenOrCreated)
  1143. {
  1144. //
  1145. // top 32bits of 64bit handle are guaranteed to be zero
  1146. //
  1147. pTG->Inst.hfile = TiffCreateW ( pTG->lpwFileName,
  1148. tiffCompression,
  1149. pTG->TiffInfo.ImageWidth,
  1150. FILLORDER_LSB2MSB,
  1151. HiRes
  1152. );
  1153. if (! (pTG->Inst.hfile))
  1154. {
  1155. #ifdef DEBUG
  1156. LPSTR lpsTemp = UnicodeStringToAnsiString(pTG->lpwFileName);
  1157. DebugPrintEx( DEBUG_ERR,
  1158. "Can't create tiff file %s compr=%d",
  1159. lpsTemp,
  1160. tiffCompression);
  1161. MemFree(lpsTemp);
  1162. #endif
  1163. return actionERROR;
  1164. }
  1165. pTG->fTiffOpenOrCreated = 1;
  1166. #ifdef DEBUG
  1167. {
  1168. LPSTR lpsTemp = UnicodeStringToAnsiString(pTG->lpwFileName);
  1169. DebugPrintEx( DEBUG_MSG,
  1170. "Created tiff file %s compr=%d HiRes=%d",
  1171. lpsTemp,
  1172. tiffCompression,
  1173. HiRes);
  1174. MemFree(lpsTemp);
  1175. }
  1176. #endif
  1177. }
  1178. uMod = pTG->ProtInst.llRecvParams.Baud;
  1179. // in non-ECM mode, PhaseC is ALWAYS with short-train.
  1180. // Only TCF uses long-train
  1181. if(uMod >= V17_START)
  1182. uMod |= ST_FLAG;
  1183. pTG->T30.sRecvBufSize = MY_BIGBUF_SIZE;
  1184. if((uRet = ModemRecvMode( pTG,
  1185. uMod,
  1186. PHASEC_TIMEOUT, FALSE)) != RECV_OK)
  1187. {
  1188. DebugPrintEx(DEBUG_WRN,"RecvMode returned %d", uRet);
  1189. PSSLogEntry(PSS_WRN, 1, "Failed to receive page %d - receiving commands", pTG->PageCount+1);
  1190. pTG->EchoProtect.modePrevRecv = modeNONECM;
  1191. // set global flag if we got WRONGMODE
  1192. pTG->EchoProtect.fGotWrongMode = (uRet==RECV_WRONGMODE);
  1193. // elim flush--does no good & wastes 10ms
  1194. CLEAR_MISSED_TCFS();
  1195. return actionGONODE_F;
  1196. }
  1197. // as soon as we get good carrier ZERO the EchoProtect state
  1198. _fmemset(&pTG->EchoProtect, 0, sizeof(pTG->EchoProtect));
  1199. // PageCount gets incremented only when the page was fully received, hence +1
  1200. PSSLogEntry(PSS_MSG, 1, "Receiving page %d data...", pTG->PageCount+1);
  1201. // to mark start of Page
  1202. if(!ICommPutRecvBuf(pTG, NULL, RECV_STARTPAGE))
  1203. {
  1204. DebugPrintEx(DEBUG_ERR,"Zero return from PutRecvBuf(start page)");
  1205. return actionERROR;
  1206. }
  1207. // make it large, in case of large buffers & slow modems
  1208. #define READ_TIMEOUT 25000
  1209. lTotalLen = 0;
  1210. do
  1211. {
  1212. uRet=ModemRecvBuf(pTG, &lpbf, READ_TIMEOUT);
  1213. // lpbf==0 && uRet==RECV_OK just does nothing & loops back
  1214. if (uRet == RECV_EOF)
  1215. {
  1216. // indicate that this is actually last recv_seq (we've got dle/etx already).
  1217. DebugPrintEx(DEBUG_MSG,"fLastReadBlock = 1");
  1218. pTG->fLastReadBlock = 1;
  1219. }
  1220. if(lpbf)
  1221. {
  1222. lTotalLen += lpbf->wLengthData;
  1223. if(!ICommPutRecvBuf(pTG, lpbf, RECV_SEQ))
  1224. {
  1225. DebugPrintEx(DEBUG_ERR,"Zero return from PutRecvBuf in page");
  1226. return actionERROR;
  1227. }
  1228. lpbf = 0;
  1229. }
  1230. else
  1231. {
  1232. if ( pTG->fLastReadBlock == 1)
  1233. {
  1234. ICommPutRecvBuf(pTG, lpbf, RECV_FLUSH);
  1235. }
  1236. }
  1237. }
  1238. while(uRet == RECV_OK);
  1239. PSSLogEntry(PSS_MSG, 2, "recv: page data, %d bytes", lTotalLen);
  1240. if(uRet == RECV_EOF)
  1241. {
  1242. pTG->T30.fAtEndOfRecvPage = TRUE;
  1243. // call this *after* getting MPS/EOM/EOP
  1244. // PutRecvBuf(NULL, RECV_ENDPAGE); // to mark end of Page
  1245. pTG->T30.fReceivedPage = TRUE;
  1246. }
  1247. else
  1248. {
  1249. // Timeout from ModemRecvBuf
  1250. DebugPrintEx(DEBUG_ERR,"DataRead Timeout or Error=%d", uRet);
  1251. PSSLogEntry(PSS_ERR, 1, "Failed to receive page data - aborting");
  1252. return actionERROR; // goto error;
  1253. }
  1254. PSSLogEntry(PSS_MSG, 1, "Successfully received page data");
  1255. ECHOPROTECT(0, 0);
  1256. CLEAR_MISSED_TCFS();
  1257. PSSLogEntry(PSS_MSG, 0, "Phase D - Post message exchange");
  1258. return actionGONODE_F; // goto NodeF; // get post-message command
  1259. }
  1260. ET30ACTION NonECMRecvPhaseD(PThrdGlbl pTG)
  1261. {
  1262. ET30ACTION action;
  1263. ET30ACTION ret;
  1264. DEBUG_FUNCTION_NAME(_T("NonECMRecvPhaseD"));
  1265. /******** Receiver Phase D. Fig A-7/T.30 (sheet 2) ********/
  1266. // NodeIII:
  1267. /** Here the T30 flowchart is all BS. Fundamentally relying on
  1268. a +FCERROR response is not possible, so what we do here really
  1269. depends on what we've got. (According to the T30 flowchart we
  1270. return to NodeF after sending MCF/RTP/RTN, in all cases. What we
  1271. now know is that,
  1272. after MPS/MCF goto RecvPhaseC to get the next page
  1273. after EOM/MCF goto NodeR1 and send NSF etc all over again
  1274. ***changed*** go back to NodeF, wait for T2 timeout
  1275. before sending DIS all over again.
  1276. after EOP/MCF goto NodeF, where GetResponse() will get
  1277. a DCN and we end up in NodeB (disconnect)
  1278. after xxx/RTN or xxx/RTP, I don't know what to do, but my guess
  1279. (looking at the Sender side of T30 flowchart) is:-
  1280. after MPS/RTx goto NodeF (sender goes to NodeD)
  1281. after EOP/RTx goto NodeF (sender goes to D or C)
  1282. after EOM/RTx goto NodeR1 (sender goes to NodeT)
  1283. ***changed*** go back to NodeF, wait for T2 timeout
  1284. before sending DIS all over again.
  1285. ****/
  1286. // only MPS/EOM/EOP commands come here
  1287. if(pTG->T30.fAtEndOfRecvPage) // so we won't call this twice
  1288. {
  1289. // This calls ET30ProtRecvPageAck so that WhatNext can choose
  1290. // MCF or RTN respectively. So it *must* be done before the
  1291. // call to WhatNext below
  1292. // If we got EOM then it's not the end of the document, it's just that we want to get back
  1293. // to phase B (for negotiating).
  1294. switch(pTG->T30.ifrCommand)
  1295. {
  1296. case ifrMPS:
  1297. // There are more pages to come with the same parameters (so go back to phase C)
  1298. DebugPrintEx(DEBUG_MSG,"Got MPS, Calling PutRecvBuf with RECV_ENDPAGE");
  1299. if(!ICommPutRecvBuf(pTG, NULL, RECV_ENDPAGE))
  1300. {
  1301. DebugPrintEx(DEBUG_ERR,"failed calling PutRecvBuf with RECV_ENDPAGE");
  1302. return actionERROR;
  1303. }
  1304. break;
  1305. case ifrEOP:
  1306. // There are no more pages.
  1307. DebugPrintEx(DEBUG_MSG,"Got EOP, Calling PutRecvBuf with RECV_ENDDOC");
  1308. if(!ICommPutRecvBuf(pTG, NULL, RECV_ENDDOC))
  1309. {
  1310. DebugPrintEx(DEBUG_ERR,"failed calling PutRecvBuf with RECV_ENDDOC");
  1311. return actionERROR;
  1312. }
  1313. break;
  1314. case ifrEOM:
  1315. // More pages but with different params: width, res, encoding, modulation, etc.
  1316. DebugPrintEx(DEBUG_MSG,"Got EOM, Calling PutRecvBuf with RECV_ENDPAGE");
  1317. if(!ICommPutRecvBuf(pTG, NULL, RECV_ENDPAGE))
  1318. {
  1319. DebugPrintEx(DEBUG_ERR,"failed calling PutRecvBuf with RECV_ENDPAGE");
  1320. return actionERROR;
  1321. }
  1322. break;
  1323. default:
  1324. DebugPrintEx( DEBUG_ERR,
  1325. "got unexpected command (ifr=%d)",
  1326. pTG->T30.ifrCommand);
  1327. if(!ICommPutRecvBuf(pTG, NULL, RECV_ENDDOC)) // Mimic the former behavior
  1328. {
  1329. DebugPrintEx(DEBUG_ERR,"failed calling PutRecvBuf with RECV_ENDDOC");
  1330. return actionERROR;
  1331. }
  1332. }
  1333. pTG->T30.fAtEndOfRecvPage = FALSE;
  1334. }
  1335. // returns MCF if page was OK, or RTN if it was bad
  1336. ret=actionGONODE_F;
  1337. ECHOPROTECT(0, 0);
  1338. CLEAR_MISSED_TCFS();
  1339. switch(action = WhatNext( pTG,
  1340. eventRECVPOSTPAGECMD,
  1341. (WORD)pTG->T30.ifrCommand,
  1342. 0,
  1343. 0))
  1344. {
  1345. /* LAST PAGE WAS OK, SEND CONFIRMATION */
  1346. case actionSENDMCF:
  1347. switch(pTG->T30.ifrCommand)
  1348. {
  1349. case ifrMPS:
  1350. ECHOPROTECT(ifrMCF, modeNONECM);
  1351. ret=actionGONODE_RECVPHASEC;
  1352. break;
  1353. case ifrEOP:
  1354. ECHOPROTECT(ifrMCF, 0);
  1355. CLEAR_MISSED_TCFS();
  1356. ret=actionNODEF_SUCCESS;
  1357. break;
  1358. case ifrEOM:
  1359. CLEAR_MISSED_TCFS();
  1360. ret=actionGONODE_R1;
  1361. break;
  1362. default:
  1363. DebugPrintEx( DEBUG_ERR,
  1364. "Got unknown command not (MCF,EOM or MPS)");
  1365. }
  1366. PSSLogEntry(PSS_MSG, 1, "Sending MCF");
  1367. if (!SendMCF(pTG))
  1368. {
  1369. PSSLogEntry(PSS_ERR, 1, "Failed to send MCF");
  1370. }
  1371. else
  1372. {
  1373. PSSLogEntry(PSS_MSG, 1, "Successfully sent MCF");
  1374. }
  1375. break;
  1376. /* LAST PAGE WAS BAD, SEND RTN or DCN */
  1377. case actionSENDRTN:
  1378. ECHOPROTECT(ifrRTN, 0);
  1379. // After that we will return actionGONODE_F
  1380. PSSLogEntry(PSS_MSG, 1, "Sending RTN");
  1381. if (!SendRTN(pTG))
  1382. {
  1383. PSSLogEntry(PSS_ERR, 1, "Failed to send RTN");
  1384. }
  1385. else
  1386. {
  1387. PSSLogEntry(PSS_MSG, 1, "Successfully sent RTN");
  1388. }
  1389. break;
  1390. case actionHANGUP:
  1391. DebugPrintEx( DEBUG_ERR,
  1392. "Got actionHANGUP from eventRECVPOSTPAGECMD");
  1393. ret=actionHANGUP;
  1394. break;
  1395. // case actionSENDRTP: SendRTP(pTG); break; // never send RTP
  1396. case actionERROR: ret=action; break; // goto PhaseLoop & exit
  1397. default: return actionERROR;
  1398. }
  1399. if (ret == actionNODEF_SUCCESS)
  1400. {
  1401. PSSLogEntry(PSS_MSG, 0, "Phase E - Hang up");
  1402. }
  1403. return ret;
  1404. }
  1405. /***************************************************************************
  1406. Name : IFR GetCmdResp(BOOL fCommand)
  1407. Purpose : Implement the "Command Received" and "Response Received"
  1408. subroutines in the T.30 flowchart. The following macros are
  1409. defined:-
  1410. #define GetResponse() GetCmdResp(FALSE)
  1411. #define GetCommand() GetCmdResp(TRUE)
  1412. where the first form results in a faithful implem.
  1413. of the "Response Received" subroutine, the 2nd one
  1414. changes two things (i) the timeout for getting falgs goes from
  1415. T4 to T2, and (ii) if the routine times out on the very
  1416. first frame without getting flags (i.e. T2 times out)
  1417. it returns ifrTIMEOUT. This results in the "Command Recvd"
  1418. and the enclosing T2 loop being implemented in this
  1419. routine.
  1420. Upon receiving a set of frames, this routine assembles them
  1421. into the ET30FR structs pointed to by rglpfr, and if any
  1422. of them have a non-null FIF, or if >1 frame are received, it
  1423. calls (*Callbacks.Callbacks.lpWhatNext)().
  1424. Finally it returns the ifr of the last frame received, if
  1425. all frames were good, or ifrBAD if *all* frames were bad.
  1426. The algorithm it implements is very close to the "Response
  1427. Received" flowchart, minus the "Transmit DCN" box & below.
  1428. It returns ifrNULL or ifrBAD corresponding to return via
  1429. Node 2, (i.e. ifrNULL for timeout and other errors), ifrBAD
  1430. for bad frames, *iff* it can resync and get 200ms of silence
  1431. following these. ifrERROR for Node 1 (i.e. any error or timeout
  1432. after which we cannot resync or get silence for 200ms),
  1433. and ifrDCN for Node 3 (i.e. DCN was received).
  1434. <<<Node1 (ifrERROR does not make sense, so we dont use it. On error
  1435. we immediately return BAD or NULL or TIMEOUT and allow retry>>>
  1436. The "Optional Response" box is replaced by a "Not final frame".
  1437. A "start T4" box is assumed at "Enter" and a "Reset T4" box
  1438. is assumed after "process optional response"
  1439. It also modifies the flowchart in that *all* the frames are got
  1440. until a final frame, even if an FCS error frame is recvd. This
  1441. is partly because after an erroneous frame we have absolutely
  1442. no idea how long to wait until we either get silence or timeout
  1443. and hangup. ALso it may be more robust. The main routine
  1444. throws away the entire set of frames if one is bad.
  1445. The callback function is called before any return and it gets
  1446. a pointer to the desired return vakue, so it can modify this.
  1447. Arguments: whether it is called as "Command Received" or as
  1448. "Response Received"
  1449. Returns : ifrNULL -- timeout
  1450. ifrTIMEOUT -- T2 timed out before first flag
  1451. (returns this if and only if fCommand==TRUE)
  1452. ifrBAD -- all frames received were bad
  1453. ifrDCN -- DCN was received. The only valid action is "goto NodeB"
  1454. ifrXXXX -- last received frame
  1455. Calls :
  1456. Called By: GetResponse() GetCommand1() and GetCommand2() macros (ONLY!)
  1457. These are called only from ET30MainBody.
  1458. Comment : Watch out for timeouts > 65535 (max UWORD)
  1459. Revision Log
  1460. Date Name Description
  1461. -------- ----- ---------------------------------------------------------
  1462. 06/15/92 arulm Created for first time (completely from scratch)
  1463. ***************************************************************************/
  1464. IFR GetCmdResp(PThrdGlbl pTG, BOOL fCommand, USHORT ifrHint)
  1465. {
  1466. /*** we need to try for T4 to get a frame here. The way Class1 modems
  1467. works, as long as no flags are received, the AT+FRH=3 command will
  1468. time out and return ERROR. CONNECT is returned as soon as flags
  1469. are received. Some modems return <CR><LF>OK<CR><LF><CR><LF>CONNECT
  1470. which is still taken care of by our new ModemDialog which throws
  1471. away blank lines and looks for the expected answer i.e. "CONNECT"
  1472. in this case, in multi-line responses.
  1473. ***/
  1474. BYTE bRecv[MAXFRAMESIZE];
  1475. BOOL fFinal, fNoFlags, fGotFIF;
  1476. DWORD dwNumBadFrames;
  1477. IFR ifr, ifrLastGood;
  1478. USHORT uRet, uRecv, j;
  1479. ET30ACTION action;
  1480. LPLPFR lplpfr;
  1481. LPFR lpfrNext;
  1482. ULONG ulTimeout;
  1483. BOOL fGotEofFromRecvMode=0;
  1484. DEBUG_FUNCTION_NAME(_T("GetCmdResp"));
  1485. // need to init these first
  1486. pTG->T30.Nframes = 0;
  1487. fFinal = FALSE;
  1488. fNoFlags = TRUE;
  1489. fGotFIF = FALSE;
  1490. dwNumBadFrames = 0;
  1491. ifrLastGood = ifrNULL;
  1492. // figure out the timeout
  1493. if(fCommand)
  1494. {
  1495. ulTimeout = T2_TIMEOUT;
  1496. }
  1497. else
  1498. {
  1499. ulTimeout = T4_TIMEOUT;
  1500. }
  1501. // if we're sending DCS-TCF and waiting for CFR, we increase the timeout each time
  1502. // we fail, to avoid getting an infinite collision. This fixes bug#6847
  1503. if(ifrHint==ifrTCFresponse && pTG->T30.uTrainCount>1)
  1504. {
  1505. ulTimeout += TCFRESPONSE_TIMEOUT_SLACK;
  1506. DebugPrintEx( DEBUG_MSG,
  1507. "Get TCF response: traincount=%d timeout=%ld",
  1508. pTG->T30.uTrainCount,
  1509. ulTimeout);
  1510. }
  1511. lplpfr = pTG->T30.lpfs->rglpfr;
  1512. lpfrNext = (LPFR)(pTG->T30.lpfs->b);
  1513. pTG->T30.sRecvBufSize = 0;
  1514. uRet = ModemRecvMode(pTG, V21_300, ulTimeout, TRUE);
  1515. if(uRet == RECV_TIMEOUT || uRet == RECV_ERROR)
  1516. {
  1517. DebugPrintEx(DEBUG_WRN,"RecvMode failed=%d", uRet);
  1518. goto error;
  1519. }
  1520. else if(uRet == RECV_WRONGMODE)
  1521. {
  1522. DebugPrintEx(DEBUG_ERR,"Got FCERROR from FRH=3");
  1523. // treat like timeout
  1524. goto error;
  1525. }
  1526. else if(uRet == RECV_EOF)
  1527. {
  1528. // ModemRecvMode() returns EOF then return ifrEOF immediately. RecvMode
  1529. // returns RECV_EOF only if we pass it the ifrNODEFafterWRONGMODE hint
  1530. // and it senses silence (i.e. we saw a V21 echo but missed it). In
  1531. // this case we want to retry the high speed PIX recv again immediately
  1532. DebugPrintEx(DEBUG_WRN,"ECHO--Got EOF from V21 RecvMode");
  1533. fGotEofFromRecvMode=TRUE;
  1534. goto error;
  1535. }
  1536. pTG->fReceivedHDLCflags = TRUE; // We received CONNECT - so the other side must be a fax
  1537. for( ;!fFinal; )
  1538. {
  1539. DebugPrintEx(DEBUG_MSG,"Before ModemRecvMem, timeout = %d",ulTimeout);
  1540. uRet = ModemRecvMem(pTG, bRecv, MAXFRAMESIZE, ulTimeout, &uRecv);
  1541. DebugPrintEx(DEBUG_MSG, "After ModemRecvMem, got %d",uRecv);
  1542. if(uRet == RECV_TIMEOUT)
  1543. {
  1544. DebugPrintEx(DEBUG_WRN,"got RECV_TIMEOUT from ModemRecvMem");
  1545. goto error; // timeout in FRH=3
  1546. }
  1547. fNoFlags = FALSE;
  1548. if(uRet == RECV_EOF)
  1549. {
  1550. DebugPrintEx(DEBUG_WRN,"Got NO CARRIER, but no final bit");
  1551. goto error; // ignore good frames if we got any, because we
  1552. // must've missed the last (most important) one
  1553. // continue;
  1554. }
  1555. else if(uRet == RECV_ERROR)
  1556. {
  1557. DebugPrintEx(DEBUG_ERR,"Got RECV_ERROR at GetCmdResp!");
  1558. goto error; // error in FRH=3
  1559. }
  1560. /** Sometimes modems give use ERROR even when teh frame is good.
  1561. Happens a lot from Though to PP144MT on CFR. So we ignore the
  1562. BADFRAME response, and check the recvd data for ourselves.
  1563. First stage--check the FF-03/13-FCF. If this is OK (i.e. got
  1564. a known FCF) and no FIF reqd and data length is correct
  1565. then accept it. But if the frame requires an FIF and we
  1566. got a BADFRAME response then don't accept it even if it
  1567. looks good--too dangerous.
  1568. 2nd-stage(NYI)--keep a table of CRCs for each fixed frame & check
  1569. them ourselves.
  1570. **/
  1571. /*** Got Valid OK Frame. Now analyse it. In general here we
  1572. want to be pretty lax in recognizing frames. Oftentimes
  1573. we have mucho garbage thrown in.
  1574. <CHANGE> Actually we're checking strictly now....
  1575. If we get a bad frame, we mark this in the lpfrfr[] array
  1576. and go on to try and get another frame.
  1577. <CHANGE> We've stopped saving bad frames
  1578. ***/
  1579. // AT&T modem gives us frames w/o CRC, so we get just 1 byte here!!
  1580. // <CHNAGE> fixed that at driver level, so we always get 3 bytes here
  1581. // IFF it is a valid frame
  1582. if(uRecv < 3)
  1583. goto badframe;
  1584. if(bRecv[0] != 0xFF)
  1585. goto badframe;
  1586. if(bRecv[1] == 0x03)
  1587. {
  1588. fFinal = FALSE;
  1589. }
  1590. else if(bRecv[1] == 0x13)
  1591. {
  1592. fFinal = TRUE;
  1593. }
  1594. else
  1595. {
  1596. goto badframe;
  1597. }
  1598. for(ifr=1; ifr<ifrMAX; ifr++)
  1599. {
  1600. if(rgFrameInfo[ifr].fInsertDISBit)
  1601. {
  1602. // Mask off the DIS bit
  1603. if(rgFrameInfo[ifr].bFCF1 != (BYTE)(bRecv[2] & 0xFE))
  1604. continue;
  1605. }
  1606. else
  1607. {
  1608. if(rgFrameInfo[ifr].bFCF1 != bRecv[2])
  1609. continue;
  1610. }
  1611. j=3; // Till now the size is 3: 0xFF 0x03/0x13 and the bFCF1
  1612. if(rgFrameInfo[ifr].bFCF2)
  1613. {
  1614. // AT&T modem gives us frames w/o CRC, so we get just 1 byte frames!!
  1615. if(uRecv < 4)
  1616. goto badframe;
  1617. if((BYTE)(rgFrameInfo[ifr].bFCF2-1) != bRecv[3])
  1618. continue;
  1619. j++;
  1620. }
  1621. if(rgFrameInfo[ifr].wFIFLength == 0xFF) // var length FIF
  1622. {
  1623. // Var length frames
  1624. // Cant accept it if the modem thought they it was bad
  1625. // accept it IFF RECV_OK & FIFlen>0
  1626. if(uRet==RECV_OK && (j < uRecv))
  1627. {
  1628. fGotFIF = TRUE;
  1629. }
  1630. else
  1631. {
  1632. DebugPrintEx( DEBUG_ERR,
  1633. "Discarding Bad Frame: uRet=%d FIFlen=%d Reqd=Var",
  1634. uRet,
  1635. (uRecv-j));
  1636. goto badframe;
  1637. }
  1638. }
  1639. else if(rgFrameInfo[ifr].wFIFLength) // fixed length FIF
  1640. {
  1641. // if frame length is exactly right then accept it
  1642. // else if modem said frame was ok and length is
  1643. // longer than expected then accept it too
  1644. if((j+rgFrameInfo[ifr].wFIFLength) == uRecv)
  1645. {
  1646. fGotFIF = TRUE;
  1647. }
  1648. else if(uRet==RECV_OK && (j+rgFrameInfo[ifr].wFIFLength < uRecv))
  1649. {
  1650. fGotFIF = TRUE;
  1651. }
  1652. else
  1653. {
  1654. DebugPrintEx( DEBUG_ERR,
  1655. "Discarding Bad Frame: uRet=%d FIFlen=%d Reqd=%d",
  1656. uRet,
  1657. (uRecv-j),
  1658. rgFrameInfo[ifr].wFIFLength);
  1659. goto badframe;
  1660. }
  1661. }
  1662. else // no FIF reqd
  1663. {
  1664. if(j != uRecv)
  1665. {
  1666. DebugPrintEx( DEBUG_MSG,
  1667. "Weird frame(2) j=%d uRecv=%d",
  1668. j,
  1669. uRecv);
  1670. // see the BADFRAME comment block above on why we do this
  1671. if(uRet != RECV_OK)
  1672. goto badframe;
  1673. // accept it even if wrong length *iff* uRet==RECV_OK
  1674. // goto badframe;
  1675. // **additional** reason to do this that 2 bytes of extra
  1676. // CRC may be present. This happens because of the AT&T and
  1677. // NEC modems that doen't give CRC, so we do no CRC lopping-off
  1678. // in the modem driver. So accept it anyway here.
  1679. }
  1680. }
  1681. goto goodframe;
  1682. }
  1683. // fall through here when ifr == ifrMAX
  1684. badframe:
  1685. DebugPrintEx(DEBUG_WRN,"IGNORING Bad Frame (Size=%d) -->", uRecv);
  1686. //Protocol Dump
  1687. DumpFrame(pTG, FALSE, 0, uRecv, bRecv);
  1688. dwNumBadFrames++; // remember we got a bad frame
  1689. // Some modems can get into a state where they give many bad frames forever.
  1690. // So... limit the number of bad frames we're willing to accept in a sequence
  1691. if (dwNumBadFrames>3)
  1692. {
  1693. DebugPrintEx(DEBUG_WRN,"Received %d bad frames, maximum exceeded", dwNumBadFrames);
  1694. goto error;
  1695. }
  1696. // when we get a bad frame, the only excuse for going to the modem again
  1697. // immediately is to get rid of the following frame (it it exists)
  1698. // because we're going to dump the whole sequence anyway.
  1699. // we don't want any terminating frame in a sequence to be considered
  1700. // a stand alone frame.
  1701. // so... let's shorten the timeout, not to catch the start of the next
  1702. // batch (which will come in 3 seconds) and loop back to see if it's there.
  1703. // if this was the last frame (or only frame) and it was bad, we 'waste'
  1704. // 500ms waiting for another frame which won't come.
  1705. // but anyway we're going to wait for the next round in 3 seconds.
  1706. ulTimeout = 500;
  1707. continue;
  1708. // loop back here for the next frame
  1709. goodframe:
  1710. ifrLastGood = ifr; // save last good ifr
  1711. //
  1712. // Copy the frame into the received frames buffer
  1713. // We fill out the header and copy (uRecv-j) bytes
  1714. //
  1715. {
  1716. DWORD dwSpaceLeft = (DWORD)((LPB)lpfrNext - (LPB)pTG->T30.lpfs);
  1717. if ( ((dwSpaceLeft + sizeof(FR) + (uRecv-j)) > TOTALRECVDFRAMESPACE)
  1718. || (pTG->T30.Nframes >= MAXRECVFRAMES))
  1719. {
  1720. DebugPrintEx(DEBUG_ERR,"Out of space for received frames. Haaalp!!");
  1721. pTG->T30.Nframes = 0;
  1722. lplpfr = pTG->T30.lpfs->rglpfr;
  1723. lpfrNext = (LPFR)(pTG->T30.lpfs->b);
  1724. }
  1725. }
  1726. lpfrNext->ifr = ifr;
  1727. if(uRecv > j)
  1728. {
  1729. lpfrNext->cb = uRecv-j;
  1730. _fmemcpy(lpfrNext->fif, bRecv+j, uRecv-j);
  1731. //Protocol Dump
  1732. DumpFrame(pTG, FALSE, ifr, (USHORT)(uRecv-j), bRecv+j);
  1733. }
  1734. else
  1735. {
  1736. lpfrNext->cb = 0;
  1737. //Protocol Dump
  1738. DumpFrame(pTG, FALSE, ifr, 0, 0);
  1739. }
  1740. PSSLogEntry(PSS_MSG, 2, "frame is %s, %s frame",
  1741. ifr ? rgFrameInfo[ifr].szName : "???",
  1742. fFinal ? "final" : "non-final");
  1743. lplpfr[pTG->T30.Nframes] = lpfrNext;
  1744. pTG->T30.Nframes++;
  1745. if(ifr==ifrDCS) // The DCS could be followed by TSI (Fix bug #4672)
  1746. // "Fax: T.30: fax service cannot receive DCS(TSI) - some older fax machine send DCS(TSI)"
  1747. {
  1748. // Need to set receive speed, since bypass all callbacks
  1749. // now and go straight to AT+FRM=xx
  1750. DebugPrintEx( DEBUG_MSG,
  1751. "This is the received DCS:0x%02x - 0x%02x - 0x%02x",
  1752. (lpfrNext->fif[0]),
  1753. (lpfrNext->fif[1]),
  1754. (lpfrNext->fif[2]));
  1755. pTG->T30.uRecvTCFMod = (((lpfrNext->fif[1])>>2) & 0x0F);
  1756. DebugPrintEx( DEBUG_MSG,
  1757. "cmdresp-DCS fx sp=%d last ifr=%d",
  1758. pTG->T30.uRecvTCFMod,
  1759. ifr);
  1760. // fastexit:
  1761. return ifr; // ifr of final/command frame
  1762. }
  1763. lpfrNext++; // skips over only the base part of frame
  1764. lpfrNext = (LPFR)((LPBYTE)lpfrNext + (uRecv-j)); // skips over FIF too
  1765. if(ifr == ifrCRP)
  1766. {
  1767. dwNumBadFrames++; // pretend we got a bad response (so the T30 chart says!)
  1768. goto error; // exit, but get 200ms of silence
  1769. // caller will resend command
  1770. }
  1771. if(ifr == ifrDCN)
  1772. {
  1773. goto exit2; // exit. Don't call callback function!
  1774. }
  1775. // loop back here for the next frame
  1776. }
  1777. // let ifrDCN also come through here. No hurry, so we can report
  1778. // it to the protocol module. If we got *only* bad frames, here we'll
  1779. // return ifrBAD
  1780. //exit:
  1781. if ( !pTG->T30.Nframes || // we got no good frames
  1782. (ifr != ifrLastGood)|| // final frame was bad
  1783. dwNumBadFrames )
  1784. {
  1785. DebugPrintEx( DEBUG_WRN,
  1786. "Got %d good frames. LastGood=%d Last=%d. Ignoring ALL",
  1787. pTG->T30.Nframes,
  1788. ifrLastGood,
  1789. ifr);
  1790. goto error;
  1791. }
  1792. // ifr of final frame
  1793. if(pTG->T30.Nframes>1 || fGotFIF)
  1794. {
  1795. action=WhatNext( pTG,
  1796. eventGOTFRAMES,
  1797. pTG->T30.Nframes,
  1798. (ULONG_PTR)lplpfr,
  1799. (ULONG_PTR)((LPIFR)&ifr));
  1800. }
  1801. exit2:
  1802. // ifr can be changed by callback function (e.g. if bad FIFs)
  1803. if(ifr==ifrDTC)
  1804. pTG->T30.fReceivedDTC = TRUE;
  1805. return ifr; // ifr of final frame
  1806. error:
  1807. // comes here on getting RECV_TIMEOUT, RECV_WRONGMODE, RECV_ERROR
  1808. // and ifrCRP, or on getting no Frames
  1809. #ifdef DEBUG
  1810. if(pTG->T30.Nframes>0 && ifr!=ifrCRP && ifrLastGood!=ifrCRP)
  1811. {
  1812. DebugPrintEx( DEBUG_ERR,
  1813. "Got some good frames--Throwing away!! IFR=%d Last=%d",
  1814. ifr,
  1815. ifrLastGood);
  1816. }
  1817. #endif
  1818. if(dwNumBadFrames)
  1819. {
  1820. ifr = ifrBAD; // caller can send CRP if desired
  1821. }
  1822. else
  1823. {
  1824. ifr = ifrNULL; // caller can repeat command & try again
  1825. }
  1826. if(fCommand && fNoFlags)
  1827. ifr = ifrTIMEOUT; // hook for "Command Recvd?"
  1828. // may not need this on TIMEOUT since AT-OK has already been
  1829. // called in ModemDialog. Probably need it on ERROR
  1830. if(uRet==RECV_ERROR)
  1831. {
  1832. iModemSyncEx(pTG, RESYNC_TIMEOUT2,0);
  1833. }
  1834. // ModemRecvMode() returns EOF then return ifrEOF immediately. RecvMode
  1835. // returns RECV_EOF only if we pass it the ifrNODEFafterWRONGMODE hint
  1836. // and it senses silence (i.e. we saw a V21 echo but missed it). In
  1837. // this case we want to retry the high speed PIX recv again immediately
  1838. if(fGotEofFromRecvMode)
  1839. ifr=ifrEOFfromRECVMODE;
  1840. return ifr;
  1841. }