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.

836 lines
23 KiB

  1. /* File: C:\WACKER\xfer\hpr_rcv1.c (Created: 24-Jan-1994)
  2. * created from HAWIN source file
  3. * hpr_rcv1.c -- Routines to implement HyperProtocol receiver.
  4. *
  5. * Copyright 1989,1993,1994 by Hilgraeve Inc. -- Monroe, MI
  6. * All rights reserved
  7. *
  8. * $Revision: 1 $
  9. * $Date: 10/05/98 1:16p $
  10. */
  11. // #define DEBUGSTR
  12. #include <windows.h>
  13. #include <setjmp.h>
  14. #include <stdlib.h>
  15. #include <time.h>
  16. #include <term\res.h>
  17. #include <sys\types.h>
  18. #include <sys\utime.h>
  19. #include <tdll\stdtyp.h>
  20. #include <tdll\mc.h>
  21. #include <tdll\com.h>
  22. #include <tdll\assert.h>
  23. #include <tdll\session.h>
  24. #include <tdll\load_res.h>
  25. #include <tdll\xfer_msc.h>
  26. #include <tdll\globals.h>
  27. #include <tdll\file_io.h>
  28. #if !defined(BYTE)
  29. #define BYTE unsigned char
  30. #endif
  31. #include "cmprs.h"
  32. #include "itime.h"
  33. #include "xfr_dsp.h"
  34. #include "xfr_todo.h"
  35. #include "xfr_srvc.h"
  36. #include "xfer.h"
  37. #include "xfer.hh"
  38. #include "xfer_tsc.h"
  39. #include "hpr.h"
  40. #include "hpr.hh"
  41. #include "hpr_sd.hh"
  42. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  43. * hr_decode_msg
  44. *
  45. * DESCRIPTION:
  46. * Called when a complete message has been received to decode the fields
  47. * of the message. Messages are composed of printable characters in one
  48. * or more fields separated by semicolons. Each field within a message
  49. * is considered to be independent of any others but fields are guaranteed
  50. * to be examined left to right with a message. Fields containing badly
  51. * formatted information generate an error but fields containing unrecognized
  52. * data are ignored.
  53. * Note also that certain message fields may prevent subsequent fields from
  54. * being decoded. For instance, if a partial data block 'P' field indicates
  55. * that the previous data block was no good, a restart will be requested
  56. * immediately and any undecoded fields will be ignored.
  57. *
  58. * ARGUMENTS:
  59. * mdata -- A pointer to the printable string that contains the message
  60. * fields.
  61. *
  62. * RETURNS:
  63. * A status code which can be one of:
  64. * H_OK if all fields were decoded without incident
  65. * H_BADMSGFMT if a field is of a recognized type but contains badly
  66. * formatted data.
  67. * H_NORESYNCH if a restart was needed as the result of a field but
  68. * could not be completed.
  69. * H_FILEERR if a file error occurred while processing a field
  70. * H_COMPLETE if the end of transfer field was encountered.
  71. */
  72. int hr_decode_msg(struct s_hc *hc, BYTE *mdata)
  73. {
  74. HCOM hCom;
  75. BYTE *field;
  76. BYTE mstr[20];
  77. int result = H_OK, retval, HRE_code;
  78. int i;
  79. BYTE typecode;
  80. struct st_rcv_open stRcv;
  81. hCom = sessQueryComHdl(hc->hSession);
  82. // field = _fstrtok(mdata, FstrScolon());
  83. field = strtok(mdata, ";");
  84. while (field != NULL)
  85. {
  86. switch(typecode = *field++)
  87. {
  88. case 'N' : /* number of files to expect */
  89. if (!hc->rc.files_expected)
  90. {
  91. hc->rc.files_expected = (int)atol(field);
  92. if (hc->rc.files_expected > 1 && hc->rc.single_file &&
  93. !hr_cancel(hc, HRE_TOO_MANY))
  94. return(H_BADMSGFMT); /* this may need a new status */
  95. hrdsp_filecnt(hc, hc->rc.files_expected);
  96. }
  97. break;
  98. case 'S' : /* size in bytes of all files */
  99. if (hc->rc.bytes_expected == -1L)
  100. {
  101. if ((hc->rc.bytes_expected = atol(field)) <= 0)
  102. hc->rc.bytes_expected = -1L;
  103. else
  104. hrdsp_totalsize(hc, hc->rc.bytes_expected);
  105. }
  106. break;
  107. case 'A' : /* abort current file */
  108. hrdsp_event(hc, HRE_RMTABORT);
  109. if (hc->fhdl)
  110. hr_closefile(hc, HRE_RMTABORT);
  111. break;
  112. case 'P' : /* check partial block */
  113. if ((int)atol(field) != (hc->blocksize - hc->datacnt)
  114. || (field = strchr(field, ',')) == NULL
  115. || (unsigned)atol(field + 1)
  116. != (hc->usecrc ? hc->h_crc : hc->h_checksum))
  117. if (!hr_restart(hc, HRE_DATAERR))
  118. return(H_NORESYNCH);
  119. hc->rc.checkpoint = hc->h_filebytes;
  120. hc->datacnt = hc->blocksize;
  121. hc->h_checksum = hc->h_crc = 0;
  122. break;
  123. case 'F' : /* new file */
  124. if (hc->current_filen && hc->fhdl && !hr_closefile(hc, HRE_NONE))
  125. return(H_FILEERR);
  126. /* set up for new file */
  127. hc->h_filebytes = hc->rc.checkpoint = 0L;
  128. hc->rc.filesize = -1L;
  129. hc->rc.ul_lstw = 0; /* don't know date/time */
  130. if ((int)atol(field) != ++hc->current_filen ||
  131. (field = strchr(field, ',')) == NULL)
  132. return(H_BADMSGFMT);
  133. strcpy(hc->rc.rmtfname, ++field);
  134. hc->rc.filesize = -1L;
  135. /* set up argument structure and let transfer open the file
  136. */
  137. stRcv.pszSuggestedName = hc->rc.rmtfname;
  138. stRcv.pszActualName = hc->rc.ourfname;
  139. /* TODO: figure out how this time stuff works */
  140. stRcv.lFileTime = hc->rc.ul_cmp;
  141. // stRcv.pfnVscanOutput = hr_virus_detect;
  142. // stRcv.pfnVscanOutput = (VOID (FAR *)(VOID FAR *, USHORT))hc->rc.pfVirusCheck;
  143. // stRcv.ssmchVscanHdl = hc->rc.ssmchVscan;
  144. if ((retval = xfer_open_rcv_file(hc->hSession, &stRcv, 0L)) != 0)
  145. {
  146. switch (retval)
  147. {
  148. case -6:
  149. HRE_code = HRE_USER_REFUSED;
  150. break;
  151. case -5:
  152. HRE_code = HRE_DISK_ERR;
  153. break;
  154. case -4:
  155. HRE_code = HRE_NO_FILETIME;
  156. break;
  157. case -3:
  158. HRE_code = HRE_CANT_OPEN;
  159. break;
  160. case -2:
  161. HRE_code = HRE_OLDER_FILE;
  162. break;
  163. case -1:
  164. default:
  165. HRE_code = HRE_CANT_OPEN;
  166. break;
  167. }
  168. if (!hr_cancel(hc, HRE_code))
  169. return(H_FILEERR);
  170. }
  171. hc->fhdl = stRcv.bfHdl;
  172. hc->rc.basesize = stRcv.lInitialSize;
  173. // hc->rc.ssmchVscan = stRcv.ssmchVscanHdl;
  174. // xferMsgVirusScan(hSession, (hc->rc.ssmchVscan == (SSHDLMCH)0) ? 0:1);
  175. // hc->rc.virus_detected = FALSE;
  176. hrdsp_compress(hc, FALSE);
  177. hrdsp_newfile(hc, hc->current_filen, hc->rc.rmtfname, hc->rc.ourfname);
  178. hc->datacnt = hc->blocksize;
  179. hc->h_checksum = hc->h_crc = 0;
  180. /* If there is no valid compare time, then the /N option is not
  181. * being used or there is no existing file and we can set up to
  182. * store received data. If there is a compare time, keep tossing
  183. * characters until we've verified that the incoming file is
  184. * newer than what we have.
  185. */
  186. if (hc->rc.ul_cmp == (unsigned long)(-1))
  187. hc->rc.hr_ptr_putc = hr_toss;
  188. //else if (hc->rc.ssmchVscan == (SSHDLMCH)0)/* is virscan active? */
  189. // hc->rc.hr_ptr_putc = hr_putc;
  190. // else
  191. //hc->rc.hr_ptr_putc = hr_putc_vir;
  192. else
  193. hc->rc.hr_ptr_putc = hr_putc;
  194. break;
  195. case 'V' : /* Version identifier from sender */
  196. i = (int)atol(field);
  197. if ((field = strchr(field, ',')) == NULL)
  198. return(H_BADMSGFMT);
  199. /* if version restrictions were found, stop the transfer */
  200. if (hpr_id_check(hc, i, ++field))
  201. break;
  202. /* else fall through */
  203. case 'X' :
  204. if (hc->rc.cancel_reason == HRE_NONE)
  205. hc->rc.cancel_reason = HRE_RMTABORT;
  206. hrdsp_event(hc, hc->rc.cancel_reason);
  207. /* fall through */
  208. case 'E' : /* end of transfer */
  209. omsg_new(hc, 'c');
  210. // StrFmt(mstr, "E%d", hc->current_filen + 1);
  211. wsprintf(mstr, "E%d", hc->current_filen + 1);
  212. omsg_add(hc, mstr);
  213. // RemoteClear(); /* get rid of any prod messages */
  214. ComRcvBufrClear(hCom);
  215. /* Sending the next message as a burst causes the excess characters
  216. * to be sent to the remote system after the transfer has ended,
  217. * perhaps causing them to dither on the display. It is tempting
  218. * to send a single message rather that a burst, but the receiver
  219. * is going to assume the transfer is done and exit after sending
  220. * this message so there is no chance for an error recovery if
  221. * the message is hit.
  222. */
  223. omsg_send(hc, BURSTSIZE, FALSE, TRUE);
  224. hc->xfertime = interval(hc->xfertimer);
  225. hrdsp_status(hc, typecode == 'E' ? HRS_COMPLETE : HRS_CANCELLED);
  226. if (hc->current_filen > 0 && hc->fhdl)
  227. {
  228. if (typecode == 'E')
  229. {
  230. if (!hr_closefile(hc, HRE_NONE))
  231. return(H_FILEERR);
  232. }
  233. else
  234. hr_closefile(hc, hc->rc.cancel_reason);
  235. }
  236. return(H_COMPLETE);
  237. case 'C' :
  238. if (strlen(field) == 0 &&
  239. !decompress_start(&hc->rc.hr_ptr_putc, hc, FALSE))
  240. {
  241. result = H_FILEERR;
  242. }
  243. else
  244. {
  245. hrdsp_compress(hc, TRUE);
  246. hc->rc.using_compression = TRUE;
  247. hrdsp_status(hc, HRS_REC);
  248. }
  249. break;
  250. case 's' :
  251. if ((hc->rc.filesize = atol(field)) > 0)
  252. hrdsp_filesize(hc, hc->rc.filesize);
  253. break;
  254. case 't' : /* file time/date */
  255. {
  256. unsigned long ulTime;
  257. struct tm stT;
  258. memset(&stT, 0, sizeof(struct tm));
  259. stT.tm_year = atoi(field); /* ?? adjust */
  260. if ((field = strchr(field, ',')) != NULL)
  261. stT.tm_mon = atoi(++field);
  262. if (field != NULL && (field = strchr(field, ',')) != NULL)
  263. stT.tm_mday = atoi(++field);
  264. if (field != NULL && (field = strchr(field, ',')) != NULL)
  265. stT.tm_hour = atoi(++field);
  266. if (field != NULL && (field = strchr(field, ',')) != NULL)
  267. stT.tm_min = atoi(++field);
  268. if (field != NULL && (field = strchr(field, ',')) != NULL)
  269. stT.tm_sec = atoi(++field);
  270. ulTime = mktime(&stT);
  271. if ((long)ulTime == (-1))
  272. ulTime = 0;
  273. else
  274. ulTime -= itimeGetBasetime();
  275. hc->rc.ul_lstw = ulTime;
  276. /*
  277. * if hc->rc.ul_cmp contains a valid date/time, it means that
  278. * the /N options was used and the file being received already
  279. * exists. Compare the two times and reject any file that is
  280. * not newer than what we already have.
  281. */
  282. if (hc->rc.ul_cmp != 0)
  283. {
  284. if (hc->rc.ul_cmp >= hc->rc.ul_lstw)
  285. {
  286. /* reject incoming file */
  287. hr_reject_file(hc, HRE_OLDER_FILE);
  288. hc->rc.ul_cmp = (unsigned long)(-1);
  289. }
  290. else
  291. {
  292. /* everything is OK */
  293. // if (hc->rc.ssmchVscan == (SSHDLMCH)0)
  294. hc->rc.hr_ptr_putc = hr_putc; /* no virus checking */
  295. // else
  296. // hc->rc.hr_ptr_putc = hr_putc_vir; /* use vir check */
  297. hc->rc.ul_cmp = 0;
  298. }
  299. }
  300. }
  301. break;
  302. case 'B' :
  303. hc->blocksize = (int)atol(field);
  304. break;
  305. case 'D' :
  306. hc->deadmantime = atol(field) * 10;
  307. break;
  308. case 'I' :
  309. hr_still_alive(hc, TRUE, FALSE);
  310. break;
  311. case 'T' :
  312. if ((i = (int)atol(field)) == 1)
  313. hc->usecrc = FALSE;
  314. else if (i == 2)
  315. hc->usecrc = TRUE;
  316. else
  317. result = H_BADMSGFMT;
  318. break;
  319. default:
  320. /* ignore, might be option supported in later version */
  321. break;
  322. }
  323. // field = _fstrtok(NULL, FstrScolon());
  324. field = strtok(NULL, ";");
  325. }
  326. return(result);
  327. }
  328. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  329. * hr_reject_file
  330. *
  331. * DESCRIPTION:
  332. * Called when we are trying to reject a file that we are receiving.
  333. *
  334. * ARGUEMENTS:
  335. * reason -- why we are rejecting the file
  336. *
  337. * RETURNS:
  338. * Always TRUE
  339. */
  340. int hr_reject_file(struct s_hc *hc, int reason)
  341. {
  342. BYTE mstr[20];
  343. /* reject incoming file */
  344. omsg_new(hc, 'c');
  345. wsprintf(mstr, "A%d", hc->current_filen);
  346. omsg_add(hc, mstr);
  347. omsg_send(hc, BURSTSIZE, FALSE, TRUE);
  348. hrdsp_event(hc, reason);
  349. hr_closefile(hc, reason);
  350. return TRUE;
  351. }
  352. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  353. * hr_closefile
  354. *
  355. * DESCRIPTION:
  356. * Called when the receiver is through saving to a particular file prior
  357. * to switching to another file or finishing the transfer.
  358. *
  359. * ARGUMENTS:
  360. * reason -- an event code indicating why this file is being closed
  361. *
  362. * RETURNS:
  363. * TRUE if file is closed without problem.
  364. * FALSE if an error occurred while closing.
  365. */
  366. int hr_closefile(struct s_hc *hc, int reason)
  367. {
  368. int retcode;
  369. hrdsp_progress(hc, FILE_DONE);
  370. hc->total_thru += hc->h_filebytes;
  371. hc->total_dsp += ((hc->rc.filesize == -1) ? hc->h_filebytes : hc->rc.filesize);
  372. if (hc->fhdl != NULL)
  373. {
  374. // retcode = transfer_close_rcv_file(hc->fhdl, hr_result_codes[reason],
  375. retcode = xfer_close_rcv_file(hc->hSession,
  376. hc->fhdl,
  377. hr_result_codes[reason],
  378. hc->rc.rmtfname,
  379. hc->rc.ourfname,
  380. xfer_save_partial(hc->hSession),
  381. hc->h_filebytes + hc->rc.basesize,
  382. hc->h_useattr ? hc->rc.ul_lstw : 0L);
  383. }
  384. hc->fhdl = NULL;
  385. hc->h_filebytes = 0;
  386. hc->rc.using_compression = FALSE;
  387. hc->rc.hr_ptr_putc = hr_toss;
  388. return retcode;
  389. }
  390. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  391. * hr_cancel
  392. *
  393. * DESCRIPTION:
  394. * This routine is called when a problem or interruption during receiving
  395. * forces a cancellation of the transfer. This routine attempts to inform
  396. * the sender of the cancellation so that a graceful shutdown can be
  397. * accomplished.
  398. * It is up to the sender to actually shut down the transfer. We just send
  399. * an interruption message to the sender asking him to do so.
  400. *
  401. * ARGUMENTS:
  402. * reason -- A code providing the reason we must cancel. The reason codes
  403. * are the same as the receiver event codes defined in the header
  404. * file as HRE_*****
  405. *
  406. * RETURNS:
  407. * TRUE if the sender responded to our request within a reasonable time.
  408. * FALSE if the sender did not respond.
  409. *
  410. */
  411. int hr_cancel(struct s_hc *hc, int reason)
  412. {
  413. HCOM hCom;
  414. BYTE str[40];
  415. hCom = sessQueryComHdl(hc->hSession);
  416. if (hc->rc.cancel_reason == HRE_NONE)
  417. hc->rc.cancel_reason = reason;
  418. if (reason == HRE_LOST_CARR)
  419. return FALSE;
  420. omsg_new(hc, 'c');
  421. // StrFmt(str, "X;R%d,%lu", hc->current_filen, hc->rc.checkpoint);
  422. wsprintf(str, "X;R%d,%lu", hc->current_filen, hc->rc.checkpoint);
  423. DbgOutStr("%s\r\n", (LPSTR)str, 0,0,0,0);
  424. omsg_add(hc, str);
  425. hc->rc.hr_ptr_putc = hr_toss;
  426. // RemoteClear();
  427. ComRcvBufrClear(hCom);
  428. hc->h_filebytes = hc->rc.checkpoint;
  429. omsg_send(hc, BURSTSIZE, FALSE, FALSE);
  430. return(hr_resynch(hc, reason));
  431. }
  432. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  433. * hr_restart
  434. *
  435. * DESCRIPTION:
  436. * This routine is called when an error in the received data forces us
  437. * to restart the transfer at the last known good location. This routine
  438. * formats the interruption request message to the sender, sends the first
  439. * message, then passes control to hr_resynch to figure out when and if
  440. * the sender responds.
  441. *
  442. * ARGUMENTS:
  443. * reason -- A code indicating the reason for the restart. The codes used
  444. * are the receiver event codes itemized in the header file as
  445. * HRE_*****
  446. *
  447. * RETURNS:
  448. * TRUE if sender responds to the restart request.
  449. * FALSE if the sender does not respond within a reasonable time.
  450. */
  451. int hr_restart(struct s_hc *hc, int reason)
  452. {
  453. HCOM hCom;
  454. BYTE str[15];
  455. hCom = sessQueryComHdl(hc->hSession);
  456. omsg_new(hc, 'c');
  457. // StrFmt(str, "R%d,%lu", hc->current_filen, hc->rc.checkpoint);
  458. wsprintf(str, "R%d,%lu", hc->current_filen, hc->rc.checkpoint);
  459. omsg_add(hc, str);
  460. // RemoteClear();
  461. ComRcvBufrClear(hCom);
  462. /* Don't start accepting characters if file is being rejected due to
  463. * /N option and there is a file open to receive them.
  464. */
  465. if ((hc->rc.ul_cmp == (unsigned long)(-1)) && (hc->fhdl != NULL))
  466. // hc->rc.hr_ptr_putc = (hc->rc.ssmchVscan == (SSHDLMCH)0) ? hr_putc : hr_putc_vir;
  467. hc->rc.hr_ptr_putc = hr_putc;
  468. else
  469. hc->rc.hr_ptr_putc = hr_toss;
  470. if (hc->rc.using_compression)
  471. decompress_start(&hc->rc.hr_ptr_putc, hc, FALSE);
  472. hc->h_filebytes = hc->rc.checkpoint;
  473. omsg_send(hc, BURSTSIZE, FALSE, FALSE);
  474. if (hc->fhdl)
  475. {
  476. fio_seek(hc->fhdl,
  477. (long)hc->rc.checkpoint + hc->rc.basesize,
  478. FIO_SEEK_SET);
  479. }
  480. return(hr_resynch(hc, reason));
  481. }
  482. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  483. * hr_resynch
  484. *
  485. * DESCRIPTION:
  486. * Attempts to resynchronize the receiver with the data stream coming
  487. * from the sender. This routine is called when the receiver starts or
  488. * after any interruption where the receiver asked the sender to restart
  489. * its sending from a new location. The calling routine will have already
  490. * sent the first copy of the restart message to the sender. This routine
  491. * will monitor all messages arriving from the sender, looking for a
  492. * restart message that matches the last request sent out. This routine
  493. * will resend the restart request message at intervals to account for
  494. * possible data loss or error in either the receiver message or the
  495. * response from the sender.
  496. *
  497. * ARGUMENTS:
  498. * hSession -- The session handle
  499. * reason -- A reason code describing why the resynch must be performed.
  500. * This will be HRE_NONE only in the case of initial startup.
  501. *
  502. * RETURNS:
  503. * TRUE if resynch was successful.
  504. * FALSE if resynch failed
  505. */
  506. int hr_resynch(struct s_hc *hc, int reason)
  507. {
  508. HCOM hCom;
  509. int fStarted = FALSE;
  510. int tries = 0;
  511. int try_limit = 0;
  512. int request_again = FALSE; /* first request already made */
  513. int result, i, j;
  514. int iret;
  515. // long l;
  516. long timer, time_limit;
  517. TCHAR rcode;
  518. int mtype;
  519. BYTE *msgdata;
  520. BYTE *field;
  521. int ok;
  522. struct
  523. {
  524. int msgn;
  525. long time;
  526. } request_tbl[MAX_START_TRIES];
  527. /* this variable is not accessed if NOTIMEOUTS is on */
  528. long tmptime; /*lint -esym(550,tmptime)*/
  529. hCom = sessQueryComHdl(hc->hSession);
  530. // reason will be HRE_NONE only if this is the initial resynch call
  531. // so we will set fStarted appropriately and use it to control behavior
  532. // later on
  533. if (reason == HRE_NONE)
  534. {
  535. fStarted = FALSE;
  536. try_limit = MAX_START_TRIES;
  537. }
  538. else
  539. {
  540. fStarted = TRUE;
  541. try_limit = MAXRETRIES;
  542. hrdsp_event(hc, reason);
  543. hrdsp_status(hc, HRS_REQRESYNCH);
  544. ++hc->total_tries;
  545. hrdsp_errorcnt(hc, hc->total_tries);
  546. }
  547. // time_limit = RESYNCH_TIME; // MOBIDEM
  548. j = hc->h_resynctime;
  549. j *= 10;
  550. if (j == 0)
  551. j = RESYNCH_TIME;
  552. time_limit = j;
  553. request_tbl[0].msgn = omsg_number(hc);
  554. timer = request_tbl[0].time = startinterval();
  555. DbgOutStr("Initial:%d, %ld, %ld\r\n",
  556. request_tbl[0].msgn, timer, time_limit, 0, 0);
  557. for ( ; ; )
  558. {
  559. if (request_again)
  560. {
  561. if (++tries >= try_limit)
  562. {
  563. hrdsp_status(hc, HRS_CANCELLED);
  564. if (hc->rc.cancel_reason == HRE_NONE)
  565. hc->rc.cancel_reason = HRE_RETRYERR;
  566. return(FALSE);
  567. }
  568. if (fStarted)
  569. omsg_send(hc, BURSTSIZE, FALSE, FALSE);
  570. else
  571. omsg_send(hc, 1, FALSE, TRUE);
  572. // Record this attempt in the table so we can match up responses
  573. request_tbl[tries].msgn = omsg_number(hc);
  574. timer = request_tbl[tries].time = startinterval();
  575. ++hc->total_tries;
  576. hrdsp_errorcnt(hc, hc->total_tries);
  577. request_again = FALSE;
  578. DbgOutStr("Restart:%d, %0ld, %0ld\r\n",
  579. request_tbl[tries].msgn, timer, time_limit, 0, 0);
  580. }
  581. iret = xfer_user_interrupt(hc->hSession);
  582. if (iret == XFER_ABORT)
  583. {
  584. if (!fStarted || hc->ucancel)
  585. return(FALSE);
  586. else
  587. {
  588. return(hr_cancel(hc, HRE_USRCANCEL));
  589. }
  590. }
  591. else if (iret == XFER_SKIP)
  592. {
  593. hr_reject_file(hc, HRE_USER_SKIP);
  594. }
  595. if (xfer_carrier_lost(hc->hSession))
  596. return hr_cancel(hc, HRE_LOST_CARR);
  597. #if !defined(NOTIMEOUTS)
  598. if ((tmptime = interval(timer)) > time_limit)
  599. {
  600. request_again = TRUE;
  601. if (fStarted)
  602. // time_limit += RESYNCH_INC; // MOBIDEM
  603. {
  604. j = hc->h_resynctime;
  605. j *= 10;
  606. if (j == 0)
  607. j = RESYNCH_INC;
  608. time_limit += j;
  609. }
  610. hrdsp_event(hc, HRE_NORESP);
  611. }
  612. else
  613. #endif
  614. if (mComRcvChar(hCom, &rcode) == 0)
  615. xfer_idle(hc->hSession);
  616. else if (rcode == H_MSGCHAR)
  617. {
  618. /* restart messages always start with #0 & use CRC */
  619. hc->rc.expected_msg = 0;
  620. hc->usecrc = TRUE;
  621. mtype = ' ';
  622. result = hr_collect_msg(hc, &mtype, &msgdata, H_CHARTIME);
  623. if (result == HR_KBDINT)
  624. {
  625. if (hc->ucancel)
  626. return(FALSE);
  627. else
  628. {
  629. hr_kbdint(hc);
  630. return(hr_cancel(hc, HRE_USRCANCEL));
  631. }
  632. }
  633. else if (result == HR_LOST_CARR)
  634. return hr_cancel(hc, HRE_LOST_CARR);
  635. else if (result != HR_COMPLETE) /* HR_TIMEOUT or HR_BAD??? */
  636. {
  637. DbgOutStr("Bad message\r\n", 0,0,0,0,0);
  638. if (mtype == 'R') /* probably our resynch, try again */
  639. {
  640. DbgOutStr("Bad message was type R\r\n", 0,0,0,0,0);
  641. hrdsp_event(hc, HRE_RETRYERR);
  642. request_again = TRUE;
  643. }
  644. }
  645. else if (mtype == 'R') /* good Resynch message */
  646. {
  647. if (!fStarted)
  648. hc->xfertimer = startinterval();
  649. fStarted = TRUE;
  650. field = strtok(msgdata, ";");
  651. if (field == NULL || *field++ != 'R')
  652. {
  653. DbgOutStr("Bad format\r\n", 0,0,0,0,0);
  654. request_again = TRUE;
  655. hrdsp_event(hc, HRE_ILLEGAL);
  656. }
  657. else
  658. {
  659. if (unchar(*field) != (BYTE)request_tbl[tries].msgn)
  660. {
  661. for (i = tries - 1; i >= 0; --i)
  662. if (unchar(*field) == (BYTE)request_tbl[i].msgn)
  663. {
  664. // We got a response to an earlier restart request.
  665. // Adjust the amount of time we wait for responses
  666. // based on the actual time of the message just
  667. // received.
  668. // time_limit = interval(request_tbl[i].time) +
  669. // RESYNCH_INC; // MOBIDEM
  670. j = hc->h_resynctime;
  671. j *= 10;
  672. if (j == 0)
  673. j = RESYNCH_INC;
  674. time_limit = interval(request_tbl[i].time) + j;
  675. DbgOutStr("Got %d, new time_limit=%ld\r\n",
  676. request_tbl[i].msgn, time_limit, 0,0,0);
  677. break; /* don't ask for retry */
  678. }
  679. if (i < 0)
  680. {
  681. hrdsp_event(hc, HRE_RETRYERR);
  682. request_again = TRUE;
  683. DbgOutStr("Not in table\r\n", 0,0,0,0,0);
  684. }
  685. }
  686. else
  687. {
  688. ok = TRUE;
  689. // field = _fstrtok(NULL, FstrScolon());
  690. field = strtok(NULL, ";");
  691. while (field != NULL)
  692. {
  693. switch (*field++)
  694. {
  695. case 'f':
  696. if ((int)atol(field) != hc->current_filen)
  697. ok = FALSE;
  698. break;
  699. case 'o':
  700. if (atol(field) != hc->rc.checkpoint)
  701. ok = FALSE;
  702. break;
  703. case 'B':
  704. hc->blocksize = (int)atol(field);
  705. break;
  706. case 'T' :
  707. if ((i = (int)atol(field)) == 1)
  708. hc->usecrc = FALSE;
  709. else if (i == 2)
  710. hc->usecrc = TRUE;
  711. break;
  712. default:
  713. break;
  714. }
  715. // field = _fstrtok(NULL, FstrScolon());
  716. field = strtok(NULL, ";");
  717. }
  718. if (ok)
  719. {
  720. hc->h_checksum = hc->h_crc = 0;
  721. hc->datacnt = hc->blocksize;
  722. if (reason != HRE_NONE || tries > 0)
  723. hrdsp_event(hc, HRE_ERRFIXED);
  724. hrdsp_status(hc, HRS_REC);
  725. DbgOutStr("Resynch successful\r\n", 0,0,0,0,0);
  726. return(TRUE);
  727. }
  728. else
  729. {
  730. hrdsp_event(hc, HRE_RETRYERR);
  731. request_again = TRUE;
  732. DbgOutStr("Not OK\r\n", 0,0,0,0,0);
  733. }
  734. }
  735. }
  736. }
  737. }
  738. }
  739. /*lint -unreachable*/
  740. }
  741. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  742. * hr_virus_detect
  743. *
  744. * DESCRIPTION:
  745. *
  746. *
  747. * ARGUMENTS:
  748. *
  749. *
  750. * RETURNS:
  751. *
  752. */
  753. #if FALSE
  754. STATICF VOID _export PASCAL hr_virus_detect(VOID FAR *h, USHORT usMatchId)
  755. {
  756. hc->rc.virus_detected = TRUE; /* force cancel of transfer */
  757. }
  758. #endif
  759. /********************** end of hpr_rcv1.c ************************/