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.

610 lines
17 KiB

  1. /* File: C:\WACKER\xfer\hpr_snd1.c (Created: 26-Jan-1994)
  2. * created from HAWIN source file
  3. * hpr_snd1.c -- Routines to provide HyperProtocol file send function in
  4. * HyperACCESS.
  5. *
  6. * Copyright 1989,1994 by Hilgraeve Inc. -- Monroe, MI
  7. * All rights reserved
  8. *
  9. * $Revision: 1 $
  10. * $Date: 10/05/98 1:16p $
  11. */
  12. #include <windows.h>
  13. #include <stdlib.h>
  14. #include <setjmp.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\load_res.h>
  22. #include <tdll\xfer_msc.h>
  23. #include <tdll\globals.h>
  24. #include <tdll\file_io.h>
  25. #if !defined(BYTE)
  26. #define BYTE unsigned char
  27. #endif
  28. #include "itime.h"
  29. #include "cmprs.h"
  30. #include "xfr_dsp.h"
  31. #include "xfr_todo.h"
  32. #include "xfr_srvc.h"
  33. #include "xfer.h"
  34. #include "xfer.hh"
  35. #include "xfer_tsc.h"
  36. #include "hpr.h"
  37. #include "hpr.hh"
  38. #include "hpr_sd.hh"
  39. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  40. * hs_namecheck
  41. *
  42. * DESCRIPTION:
  43. * This function is called to check the extension on a filename and to guess
  44. * if it should be compressed or not.
  45. *
  46. * ARGUEMENTS:
  47. * ft -- struct s_ftbl *, contains the name and gets the flag value
  48. *
  49. * RETURNS:
  50. * Nothing, but may set flags in the structure passed as arguement
  51. */
  52. void hs_namecheck(struct s_ftbl *ft)
  53. {
  54. BYTE *ptr;
  55. if (strlen(ft->fname) < 5)
  56. return;
  57. ptr = ft->fname + strlen(ft->fname) - 4;
  58. if (*ptr++ != '.')
  59. return;
  60. /* the extensions we are currently checking for are:
  61. * ARC
  62. * LZH
  63. * PAK
  64. * ZIP
  65. * ZOO
  66. */
  67. #if FALSE
  68. /* TODO: replace with something else ANSI compatible */
  69. if ((strnicmp(ptr, "ARC", 3) == 0) ||
  70. (strnicmp(ptr, "LZH", 3) == 0) ||
  71. (strnicmp(ptr, "PAK", 3) == 0) ||
  72. (strnicmp(ptr, "ZIP", 3) == 0) ||
  73. (strnicmp(ptr, "ZOO", 3) == 0))
  74. bitset(ft->cntrl, FTC_DONT_CMPRS);
  75. #endif
  76. }
  77. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  78. * hs_filebreak
  79. *
  80. * DESCRIPTION:
  81. * Handles changes to the currently open file. This routine is called whenever
  82. * the data loading routine gets an EOF while attempting to load the next
  83. * data character. This can happen when the program first starts or when
  84. * a file is exhausted or when a file error is encountered. It can also
  85. * occur artificially when, for example, a restart is requested to force
  86. * a change in file or file position.
  87. *
  88. * ARGUMENTS:
  89. * nfiles -- Total number of files expected to be sent during this transfer.
  90. * This is only used in the initial (file 0) control message.
  91. * nbytes -- Total number of bytes expected to be sent during this transfer.
  92. * This is only used in the initial (file 0) control message.
  93. *
  94. * RETURNS:
  95. * nothing
  96. */
  97. void hs_filebreak(struct s_hc *hc, int nfiles, long nbytes)
  98. {
  99. BYTE str[90];
  100. BYTE name_to_send[FNAME_LEN];
  101. struct s_ftbl *ft;
  102. /* we've either hit a real EOF, or the restart routine
  103. has backed us up into an aborted file, or we're just
  104. starting, or we've encountered a file error, or user cancelled.
  105. */
  106. omsg_new(hc, 'C');
  107. if (hc->datacnt > 0)
  108. {
  109. /* put partial block record in message */
  110. wsprintf(str, "P%u,%u", hc->datacnt,
  111. (hc->usecrc ? hc->h_crc : hc->h_checksum));
  112. omsg_add(hc, str);
  113. hc->datacnt = hc->h_crc = hc->h_checksum = 0;
  114. }
  115. if (hc->ucancel || hc->sc.rmtcancel)
  116. {
  117. hpr_id_get(hc, str);
  118. omsg_add(hc, str);
  119. omsg_add(hc, "X");
  120. hs_waitack(hc);
  121. }
  122. if (hc->current_filen == 0)
  123. {
  124. /* just getting started or need to start over */
  125. /* put 'V', 'B', 'D', 'N', and 'S' records in message */
  126. hpr_id_get(hc, str); /* add 'V' field */
  127. omsg_add(hc, str);
  128. wsprintf(str, "B%d;D%d;N%u;S%lu", hc->blocksize,
  129. (int)(hc->deadmantime / 10), nfiles, nbytes);
  130. omsg_add(hc, str);
  131. }
  132. else
  133. {
  134. #if FALSE
  135. /* TODO: put this back in later */
  136. if (fio_error(hc->fhdl))
  137. {
  138. /* print error message on the screen */
  139. hc->sc.hs_ftbl[hc->sc.ft_current].status = TSC_DISK_ERROR;
  140. }
  141. #endif
  142. if (hc->sc.hs_ftbl[hc->sc.ft_current].status != TSC_OK)
  143. {
  144. strcpy(str, "A");
  145. omsg_add(hc, str);
  146. }
  147. }
  148. /* scan up the file table looking for first non-cancelled file or
  149. * for top of table
  150. */
  151. while (++hc->sc.ft_current <= hc->sc.ft_top
  152. && hc->sc.hs_ftbl[hc->sc.ft_current].status != TSC_OK)
  153. {
  154. xfer_name_to_send(hc->hSession,
  155. hc->sc.hs_ftbl[hc->sc.ft_current].fname,
  156. name_to_send);
  157. wsprintf(str, "F%u,%s",
  158. hc->current_filen = hc->sc.hs_ftbl[hc->sc.ft_current].filen,
  159. name_to_send);
  160. omsg_add(hc, str);
  161. /* put size field in so rcvr can keep display accurate */
  162. wsprintf(str, "s%lu", hc->sc.hs_ftbl[hc->sc.ft_current].flength);
  163. omsg_add(hc, str);
  164. omsg_send(hc, 1, hc->usecrc, FALSE);
  165. /* now that we've started this file, tell receiver to abort it
  166. * right away since its status is no longer TSC_OK
  167. */
  168. omsg_new(hc, 'C');
  169. strcpy(str, "A");
  170. omsg_add(hc, str);
  171. }
  172. /* Now we should be ready for next file. We're either pointing at a
  173. * normal file in the table to be restarted or we're at the top
  174. * of the table and its time to open the next file
  175. */
  176. hc->sc.hs_ptrgetc = hs_getc;
  177. /* set pointer into table for speed */
  178. ft = &hc->sc.hs_ftbl[hc->sc.ft_current];
  179. if (hc->sc.ft_current <= hc->sc.ft_top)
  180. {
  181. /* try to reopen a file from the table */
  182. hc->current_filen = ft->filen;
  183. if (hc->fhdl != NULL && hc->sc.ft_current == hc->sc.ft_open)
  184. {
  185. /* file is already open */
  186. fio_seek(hc->fhdl, 0, FIO_SEEK_SET);
  187. }
  188. else
  189. {
  190. /* reopen previously opened file */
  191. if (hc->fhdl)
  192. {
  193. fio_close(hc->fhdl);
  194. }
  195. hc->fhdl = NULL;
  196. hc->sc.ft_open = hc->sc.ft_current;
  197. hc->current_filen = ft->filen;
  198. hc->h_filebytes = hc->sc.bytes_sent = 0L;
  199. hc->total_dsp = ft->dsp_bytes;
  200. hc->total_thru = ft->thru_bytes;
  201. if (xfer_opensendfile(hc->hSession, &hc->fhdl, ft->fname,
  202. &ft->flength, NULL, NULL) != 0)
  203. {
  204. /* display error */
  205. ft->status = TSC_CANT_OPEN;
  206. hc->sc.hs_ptrgetc = hs_reteof;
  207. hc->sc.ft_open = -1;
  208. }
  209. }
  210. }
  211. else if (xfer_nextfile(hc->hSession, name_to_send))
  212. {
  213. /* There are no more previously started files in the table to be
  214. * restarted, but there is another brand new file to send
  215. */
  216. if (hc->sc.ft_top >= hc->sc.ft_limit)
  217. {
  218. hsdsp_event(hc, HSE_FULL);
  219. hsdsp_status(hc, HSS_WAITACK);
  220. omsg_add(hc, "I");
  221. omsg_send(hc, 1, hc->usecrc, FALSE);
  222. omsg_new(hc, 'C');
  223. HS_XMIT_FLUSH(hc);
  224. while(hc->sc.ft_top >= hc->sc.ft_limit)
  225. {
  226. hs_background(hc); /* wait for space in table */
  227. hs_logx(hc, FALSE);
  228. }
  229. hsdsp_event(hc, HSE_GOTACK);
  230. hsdsp_status(hc, HSS_SENDING);
  231. /* items may shift in hs_ftbl during hs_background */
  232. ft = &hc->sc.hs_ftbl[hc->sc.ft_current];
  233. }
  234. /* open next file and install it in the table */
  235. if (hc->fhdl)
  236. {
  237. fio_close(hc->fhdl);
  238. }
  239. hc->fhdl = NULL;
  240. strcpy(ft->fname, name_to_send);
  241. ft->filen = ++hc->current_filen;
  242. ft->cntrl = 0;
  243. ft->status = TSC_OK;
  244. hs_namecheck(ft);
  245. hc->total_dsp = ft->dsp_bytes =
  246. hc->sc.hs_ftbl[hc->sc.ft_top].dsp_bytes +
  247. hc->sc.hs_ftbl[hc->sc.ft_top].flength;
  248. hc->total_thru = ft->thru_bytes =
  249. hc->sc.hs_ftbl[hc->sc.ft_top].thru_bytes + hc->h_filebytes;
  250. hc->sc.ft_top = hc->sc.ft_open = hc->sc.ft_current;
  251. hc->h_filebytes = hc->sc.bytes_sent = 0;
  252. if (xfer_opensendfile(hc->hSession, &hc->fhdl, ft->fname, &ft->flength,
  253. NULL, NULL) != 0)
  254. {
  255. /* display error? */
  256. hc->fhdl = NULL;
  257. ft->status = TSC_CANT_OPEN;
  258. hc->sc.ft_open = -1;
  259. hc->sc.hs_ptrgetc = hs_reteof;
  260. }
  261. }
  262. else /* no more files in table and no new files to send */
  263. {
  264. if (hc->fhdl)
  265. {
  266. fio_close(hc->fhdl);
  267. }
  268. hc->sc.ft_open = -1;
  269. hc->fhdl = NULL;
  270. --hc->sc.ft_current; /* don't point off top of table */
  271. hsdsp_event(hc, HSE_DONE);
  272. omsg_add(hc, "E");
  273. hs_waitack(hc);
  274. }
  275. /* put file name and attribute records in message */
  276. xfer_name_to_send(hc->hSession, ft->fname, name_to_send);
  277. wsprintf(str, "F%d,%s", ft->filen, name_to_send);
  278. omsg_add(hc, str);
  279. wsprintf(str, "s%lu", ft->flength);
  280. omsg_add(hc, str);
  281. if (hc->fhdl)
  282. {
  283. unsigned long ftime;
  284. struct tm *pT;
  285. ftime = itimeGetFileTime(ft->fname);
  286. ftime += itimeGetBasetime(); /* fudge for C 7 and later */
  287. pT = localtime(&ftime);
  288. wsprintf(str, "t%d,%d,%d,%d,%d,%d",
  289. pT->tm_year + 1900,
  290. pT->tm_mon,
  291. pT->tm_mday,
  292. pT->tm_hour,
  293. pT->tm_min,
  294. pT->tm_sec);
  295. omsg_add(hc, str);
  296. #if FALSE
  297. if (hc->sc.rmt_compress && h_trycompress &&
  298. !bittest(ft->cntrl, FTC_DONT_CMPRS) &&
  299. ft->flength > CMPRS_MINSIZE &&
  300. compress_start(&hc->sc.hs_ptrgetc, &h_filebytes, FALSE))
  301. #endif
  302. if (hc->sc.rmt_compress && hc->h_trycompress &&
  303. !bittest(ft->cntrl, FTC_DONT_CMPRS) &&
  304. ft->flength > CMPRS_MINSIZE &&
  305. compress_start(&hc->sc.hs_ptrgetc, hc, &hc->h_filebytes, FALSE))
  306. {
  307. hsdsp_compress(hc, ON);
  308. /* hsdsp_status(hc, HSS_SENDING); */
  309. omsg_add(hc, "C");
  310. bitset(ft->cntrl, FTC_COMPRESSED);
  311. }
  312. else
  313. {
  314. hsdsp_compress(hc, OFF);
  315. bitclear(ft->cntrl, FTC_COMPRESSED);
  316. }
  317. }
  318. omsg_send(hc, 1, hc->usecrc, FALSE);
  319. HS_XMIT_FLUSH(hc);
  320. hsdsp_newfile(hc, ft->filen, ft->fname, ft->flength);
  321. hsdsp_progress(hc, 0);
  322. }
  323. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  324. * hs_waitack
  325. *
  326. * DESCRIPTION:
  327. * Called at the end of a transfer to wait for the final acknowldgement from
  328. * receiver or until a restart message forces us to back up and retransmit
  329. * some of the data. This routine never returns directly to its caller. It
  330. * always exits by way of a longjmp either during a hs_background call if
  331. * an 'END' or 'RESTART' message is received or at the end of the function
  332. * if it times out without receiving either message.
  333. *
  334. * ARGUMENTS:
  335. * none
  336. *
  337. * RETURNS:
  338. * nothing (see DESCRIPTION)
  339. */
  340. void hs_waitack(struct s_hc *hc)
  341. {
  342. long timer;
  343. omsg_send(hc, 1, hc->usecrc, FALSE);
  344. hc->sc.receiver_timedout = FALSE;
  345. HS_XMIT_FLUSH(hc);
  346. hsdsp_status(hc, HSS_WAITACK);
  347. timer = startinterval();
  348. /* wait for 60 seconds, until longjmp either restarts or ends transfer */
  349. while (interval(timer) < FINAL_ACK_WAIT)
  350. {
  351. hs_background(hc);
  352. if (hc->sc.receiver_timedout)
  353. {
  354. /* receiver must have missed our end of transfer message */
  355. omsg_send(hc, 1, hc->usecrc, FALSE);
  356. HS_XMIT_FLUSH(hc);
  357. hc->sc.receiver_timedout = FALSE;
  358. }
  359. }
  360. /* if we get here, we didn't get response from receiver for 60 seconds */
  361. hsdsp_event(hc, HSE_NORESP);
  362. longjmp(hc->sc.jb_bailout, TSC_NO_RESPONSE);
  363. }
  364. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  365. * hs_decode_rmsg
  366. *
  367. * DESCRIPTION:
  368. * Called by hs_rcvmsg when a complete message has been received. This routine
  369. * parses and interprets the message either by recording information sent by
  370. * the receiver or by altering the course of the transfer in response to an
  371. * interruption message. There may be several fields in a message but note
  372. * that certain messages transfer control elsewhere via a longjmp and thus
  373. * prevent any subsequent fields from being scanned ('E', 'X', and 'R'
  374. * messages specifically). All messages from the receiver to the sender are
  375. * sent in printable characters.
  376. *
  377. * ARGUMENTS:
  378. * data -- A string containing the messages to be interpreted. Each message
  379. * is in the form of: 'T<data>;'
  380. * where T is a single character message identifier and <data> is
  381. * optional associated information.
  382. *
  383. * RETURNS:
  384. * nothing
  385. * (exits via a longjmp when certain interruption messages are received)
  386. */
  387. void hs_decode_rmsg(struct s_hc *hc, BYTE *data)
  388. {
  389. BYTE *field;
  390. int filenum;
  391. int mnum;
  392. int tval;
  393. if (data[0] != 'c') /* this is the only kind we know about now but don't */
  394. return; /* consider it an error if newer versions send */
  395. /* other types */
  396. mnum = unchar(data[2]);
  397. field = strtok(&data[3], ";");
  398. while (field != NULL)
  399. {
  400. switch(*field++)
  401. {
  402. case 'f': /* receiver has successfully received file fn */
  403. hs_fileack(hc, atoi(field));
  404. break;
  405. case 'B': /* receiver is requesting a particular block size */
  406. if (hc->current_filen == 0)
  407. {
  408. tval = atoi(field);
  409. tval = max(tval, H_MINBLOCK);
  410. hc->blocksize = min(hc->blocksize, tval);
  411. }
  412. break;
  413. case 'D': /* receiver is requesting a particular deadman time */
  414. tval = atoi(field);
  415. tval = max(tval, H_MINDEADMAN);
  416. hc->deadmantime = min(hc->deadmantime, tval * 10);
  417. break;
  418. case 'T': /* receiver is requesting check type */
  419. hc->sc.rmtchkt = atoi(field);
  420. break;
  421. case 'C': /* receiver is agreeing to do compression */
  422. if (!*field)
  423. hc->sc.rmt_compress = TRUE;
  424. break;
  425. case 'E': /* receiver is acknowledging end of transfer */
  426. hc->xfertime = interval(hc->xfertimer);
  427. if (*field)
  428. hs_fileack(hc, atoi(field));
  429. hsdsp_event(hc, HSE_GOTACK);
  430. if (!hc->ucancel && !hc->sc.rmtcancel)
  431. longjmp(hc->sc.jb_bailout, TSC_COMPLETE);
  432. else
  433. longjmp(hc->sc.jb_bailout,
  434. hc->ucancel ? TSC_USER_CANNED : TSC_RMT_CANNED);
  435. break;
  436. case 'X': /* receiver is requesting a cancellation of the xfer */
  437. if (*field)
  438. hs_fileack(hc, atoi(field));
  439. hsdsp_event(hc, HSE_RMTCANCEL);
  440. hc->sc.rmtcancel = TRUE;
  441. hc->sc.hs_ptrgetc = hs_reteof;
  442. break;
  443. case 'A': /* receiver is aborting a single file */
  444. hs_fileack(hc, filenum = atoi(field)); /* all earlier files ok */
  445. /* If we're still sending the file being cancelled, mark it
  446. * cancelled and set the character function pointer to hs_reteof
  447. * to force a switch to the next file, if any.
  448. * If we've already finished sending the file being cancelled,
  449. * look it up in the file table and mark if cancelled so that
  450. * if we're asked to back up into it, we won't bother resending
  451. * it
  452. */
  453. if (hc->current_filen == filenum)
  454. {
  455. hc->sc.hs_ftbl[hc->sc.ft_current].status = TSC_RMT_CANNED;
  456. hc->sc.hs_ptrgetc = hs_reteof; /* force switch to next file */
  457. }
  458. else
  459. {
  460. /* we're no longer sending file being canned */
  461. for (tval = hc->sc.ft_current; tval >= 0; --tval)
  462. if (hc->sc.hs_ftbl[tval].filen == filenum)
  463. hc->sc.hs_ftbl[tval].status = TSC_RMT_CANNED;
  464. }
  465. break;
  466. case 'V':
  467. tval = atoi(field);
  468. field = strchr(field, ',');
  469. /* if version restrictions were found, stop the transfer */
  470. if (!hpr_id_check(hc, tval, ++field))
  471. {
  472. hsdsp_event(hc, HSE_RMTCANCEL);
  473. hc->sc.rmtcancel = TRUE;
  474. hc->sc.hs_ptrgetc = hs_reteof;
  475. }
  476. break;
  477. case 'R': /* receiver is requesting a restart */
  478. if (!hc->sc.started)
  479. {
  480. hsdsp_event(hc, HSE_GOTSTART);
  481. hc->sc.started = TRUE;
  482. }
  483. else
  484. {
  485. hsdsp_event(hc, HSE_GOTRETRY);
  486. hsdsp_retries(hc, ++hc->total_tries);
  487. }
  488. tval = atoi(strtok(field, ",")); /* get file number */
  489. hs_fileack(hc, tval);
  490. hs_dorestart(hc, tval, atoi(strtok(NULL, ",")), mnum, FALSE);
  491. break;
  492. case 't': /* receiver stopped receiving data */
  493. hc->sc.receiver_timedout = TRUE;
  494. break;
  495. }
  496. field = strtok(NULL, ";");
  497. }
  498. }
  499. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  500. * hs_fileack
  501. *
  502. * DESCRIPTION:
  503. * Marks all transmitted files up to a specified file number as acknowledged,
  504. * that is, as transmitted completely. This routine merely marks the files
  505. * in the file table as complete; completed entries will be removed from the
  506. * table later by hs_logx.
  507. *
  508. * ARGUMENTS:
  509. * n -- The file number that the receiver considers current. All file numbers
  510. * lower than this can be considered complete.
  511. *
  512. * RETURNS:
  513. * nothing
  514. */
  515. void hs_fileack(struct s_hc *hc, int n)
  516. {
  517. register int ix = 0;
  518. while (ix <= hc->sc.ft_current)
  519. {
  520. if (ix <= hc->sc.ft_limit && hc->sc.hs_ftbl[ix].filen < n)
  521. bitset(hc->sc.hs_ftbl[ix].cntrl, FTC_CONFIRMED);
  522. ++ix;
  523. }
  524. }
  525. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  526. * hs_logx
  527. *
  528. * DESCRIPTION:
  529. * Logs either all acknowledged transfers or all transfers to the log file
  530. * and removes their entries from the file table. Note that the values of
  531. * hc->sc.ft_top, hc->sc.ft_current, and hc->sc.ft_open can change during this
  532. * operation.
  533. *
  534. * ARGUMENTS:
  535. * all -- if TRUE, log all regardless of confirmation
  536. *
  537. * RETURNS:
  538. * nothing
  539. */
  540. void hs_logx(struct s_hc *hc, int all)
  541. {
  542. struct s_ftbl *ftptr = &hc->sc.hs_ftbl[0];
  543. while (hc->sc.ft_top >= 0 && (all ||
  544. (hc->sc.ft_current > 1 && bittest(hc->sc.hs_ftbl[0].cntrl,FTC_CONFIRMED))))
  545. {
  546. if (ftptr->filen > 0)
  547. {
  548. if (ftptr->status == TSC_OK &&
  549. !bittest(ftptr->cntrl,FTC_CONFIRMED))
  550. ftptr->status = TSC_ERROR_LIMIT;
  551. xfer_log_xfer(hc->hSession,
  552. TRUE,
  553. ftptr->fname,
  554. NULL,
  555. ftptr->status);
  556. }
  557. MemCopy((char *)&hc->sc.hs_ftbl[0], (char *)&hc->sc.hs_ftbl[1],
  558. (unsigned)hc->sc.ft_top * sizeof(struct s_ftbl));
  559. --hc->sc.ft_top;
  560. --hc->sc.ft_current;
  561. --hc->sc.ft_open;
  562. }
  563. }
  564. /************************** end of hpr_snd1.c ************************/