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.

546 lines
15 KiB

  1. /* File: C:\WACKER\xfer\hpr_snd0.c (Created: 25-Jan-1994)
  2. * created from HAWIN source file
  3. * hpr_snd0.c -- Routines to provide HyperProtocol file send function in
  4. * HyperACCESS.
  5. *
  6. * Copyright 1988,89,1994 by Hilgraeve Inc. -- Monroe, MI
  7. * All rights reserved
  8. *
  9. * $Revision: 3 $
  10. * $Date: 1/11/02 1:45p $
  11. */
  12. #include <windows.h>
  13. #include <setjmp.h>
  14. #include <time.h>
  15. #include <term\res.h>
  16. #include <sys\types.h>
  17. #include <sys\utime.h>
  18. #include <tdll\stdtyp.h>
  19. #include <tdll\mc.h>
  20. #include <tdll\com.h>
  21. #include <tdll\session.h>
  22. #include <tdll\load_res.h>
  23. #include <tdll\xfer_msc.h>
  24. #include <tdll\globals.h>
  25. #include <tdll\file_io.h>
  26. #if !defined(BYTE)
  27. #define BYTE unsigned char
  28. #endif
  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. * hpr_snd
  41. *
  42. * DESCRIPTION:
  43. * Handles file sending using the Hyperprotocol transfer method.
  44. *
  45. * ARGUMENTS:
  46. * attended -- True if the program determines that a user is likely to be
  47. * present at the computer keyboard. FALSE if a user is NOT likely
  48. * to be present (such as host and script modes).
  49. * hs_nfiles -- The number of files scheduled to be sent. (Other concurrent
  50. * processes may remove files before we get to them so we may
  51. * not actually send this many files.)
  52. * hs_nbytes -- The total size of all files scheduled to be sent. (See note
  53. * in description of hs_nfiles.)
  54. *
  55. * RETURNS:
  56. * TRUE if the transfer successfully completes. FALSE otherwise.
  57. */
  58. int hpr_snd(HSESSION hSession, int attended, int hs_nfiles, long hs_nbytes)
  59. {
  60. struct s_hc *hc;
  61. HCOM hCom;
  62. int bailout;
  63. long timer;
  64. register int cc;
  65. hCom = sessQueryComHdl(hSession);
  66. hc = malloc(sizeof(struct s_hc));
  67. if (hc == NULL)
  68. return TSC_NO_MEM;
  69. memset(hc, 0, sizeof(struct s_hc));
  70. hc->hSession = hSession;
  71. /* initialize stuff */
  72. if (!hs_setup(hc, hs_nfiles, hs_nbytes))
  73. {
  74. free(hc);
  75. return TSC_NO_MEM;
  76. }
  77. /* force a file break on the next char. fetch */
  78. hc->sc.hs_ptrgetc = hs_reteof;
  79. /* initialize variables etc. */
  80. hc->h_filebytes = 0L;
  81. // hc->blocksize = 2048;
  82. // hc->blocksize = xfer_blocksize(hSession);
  83. hc->blocksize = max(hc->blocksize, H_MINBLOCK);
  84. hc->current_filen = 0;
  85. hc->deadmantime = 600;
  86. hc->total_tries = 0;
  87. hsdsp_retries(hc, hc->total_tries);
  88. hc->total_dsp = 0L;
  89. hc->total_thru = 0L;
  90. hc->ucancel = FALSE;
  91. hc->usecrc = TRUE; /* to start out */
  92. hc->fhdl = NULL;
  93. hc->sc.nfiles = hs_nfiles;
  94. hc->sc.nbytes = hs_nbytes;
  95. hc->sc.bytes_sent = hc->h_filebytes;
  96. hc->sc.rmtcancel = FALSE;
  97. hc->sc.last_response = (long)startinterval();
  98. hc->sc.lastmsgn = -1;
  99. hc->sc.rmt_compress = FALSE; /* until we hear otherwise */
  100. hc->sc.rmtchkt = H_CRC; /* until we hear otherwise */
  101. hc->sc.started = FALSE;
  102. hc->sc.lasterr_filenum = -1;
  103. hc->sc.lasterr_offset = -1L;
  104. hc->sc.sameplace = 0;
  105. /* setup file table */
  106. hc->sc.ft_current = 0;
  107. hc->sc.ft_top = hc->sc.ft_open = 0;
  108. hc->sc.hs_ftbl[0].filen = 0;
  109. hc->sc.hs_ftbl[0].cntrl = 0;
  110. hc->sc.hs_ftbl[0].status = TSC_OK;
  111. hc->sc.hs_ftbl[0].flength = 0L;
  112. hc->sc.hs_ftbl[0].thru_bytes = 0L;
  113. hc->sc.hs_ftbl[0].dsp_bytes = 0L;
  114. hc->sc.hs_ftbl[0].fname[0] = TEXT('\0');
  115. // strblank(hc->sc.hs_ftbl[0].fname);
  116. omsg_init(hc, FALSE, TRUE);
  117. if ((bailout = setjmp(hc->sc.jb_bailout)) == 0)
  118. {
  119. /* do normal transfer */
  120. // RemoteClear(); /* get rid of possible stacked-up starts */
  121. ComRcvBufrClear(hCom);
  122. /* restarts and file aborts will branch here */
  123. if (setjmp(hc->sc.jb_restart) == 0)
  124. {
  125. /* first time through, wait for receiver to begin */
  126. hsdsp_status(hc, HSS_WAITSTART);
  127. timer = (long)startinterval();
  128. #if defined(NOTIMEOUTS)
  129. while (TRUE)
  130. #else
  131. while ((long)interval(timer) < 600L)
  132. #endif
  133. {
  134. /* prevent deadman timeout */
  135. hc->xfertimer = hc->sc.last_response = (long)startinterval();
  136. hs_background(hc); /* will exit with longjump to restart */
  137. if (hc->ucancel)
  138. longjmp(hc->sc.jb_bailout, TSC_USER_CANNED);
  139. xfer_idle(hc->hSession);
  140. }
  141. hsdsp_event(hc, HSE_NORESP);
  142. longjmp(hc->sc.jb_bailout, TSC_NO_RESPONSE);
  143. }
  144. /* Restarts jump here via longjmp */
  145. hsdsp_status(hc, HSS_SENDING);
  146. hsdsp_progress(hc, 0);
  147. for (;;)/* this loop is only exited by a longjmp to hc->sc.jb_bailout */
  148. { /* or hc->sc.jb_restart */
  149. hs_background(hc);
  150. if (hs_datasend(hc))
  151. {
  152. /* sent out full data block */
  153. cc = omsg_setnum(hc, (omsg_number(hc) + 1) % 256);
  154. hc->h_checksum += (unsigned)cc;
  155. if (hc->usecrc)
  156. h_crc_calc(hc, (BYTE)cc);
  157. HS_XMIT(hc, (BYTE)cc);
  158. HS_XMIT(hc, (BYTE)((hc->usecrc?hc->h_crc:hc->h_checksum)%256));
  159. HS_XMIT(hc, (BYTE)((hc->usecrc?hc->h_crc:hc->h_checksum)/256));
  160. /* update display */
  161. hsdsp_progress(hc, 0);
  162. hc->datacnt = 0;
  163. hc->h_crc = hc->h_checksum = 0;
  164. }
  165. else /* encountered EOF in data */
  166. {
  167. if (hc->h_filebytes > 0) /* EOF probably got counted */
  168. --hc->h_filebytes;
  169. hc->sc.bytes_sent = hc->h_filebytes;
  170. hsdsp_progress(hc, FILE_DONE);
  171. hs_filebreak(hc, hs_nfiles, hs_nbytes);
  172. }
  173. xfer_idle(hc->hSession);
  174. }
  175. }
  176. else /* a longjmp(hc->sc.jb_bailout, reason) was called */
  177. {
  178. if (bailout == TSC_COMPLETE)
  179. {
  180. bailout = TSC_OK;
  181. }
  182. else
  183. {
  184. hc->xfertime = (long)interval(hc->xfertimer);
  185. if (hc->fhdl)
  186. {
  187. hc->sc.hs_ftbl[hc->sc.ft_current].status = (int)bailout;
  188. fio_close(hc->fhdl);
  189. hc->fhdl = NULL;
  190. }
  191. }
  192. hsdsp_status(hc, bailout == TSC_OK ? HSS_COMPLETE : HSS_CANCELLED);
  193. }
  194. /* cleanup and exit */;
  195. /* make sure final vu meter is displayed full */
  196. hc->total_dsp += hc->sc.hs_ftbl[hc->sc.ft_current].flength;
  197. hc->total_thru += hc->h_filebytes;
  198. hc->h_filebytes = hc->sc.bytes_sent = 0L;
  199. hsdsp_progress(hc, TRANSFER_DONE);
  200. hs_logx(hc, TRUE);
  201. hs_wrapup(hc, attended, bailout);
  202. free(hc);
  203. compress_disable();
  204. return((USHORT)bailout);
  205. }
  206. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  207. * hs_dorestart
  208. *
  209. * DESCRIPTION:
  210. * Called when an interrupt message from the receiver requests that
  211. * transmission be restarted from a particular location. (The entire
  212. * transfer is started by an initial request from the receiver to restart
  213. * at file 0, offset 0.
  214. * This routine responds to a restart request by interrupting any current
  215. * data being sent and sending a special restart message. It then sets up
  216. * to resume transmission at a new location
  217. *
  218. * ARGUMENTS:
  219. * filenum -- The file number of the file to restart.
  220. * offset -- The offset into the file specified by filenum.
  221. * msgnum -- The message number of the restart request. This number is
  222. * included in the restart message sent back so the receiver
  223. * will know which restart request it corresponds to.
  224. * abort -- True if the restart is the result of a request by the
  225. * receiving program to abort transfer of the current file.
  226. *
  227. * RETURNS:
  228. * nothing (This function always exits via a longjmp to the restart location
  229. * or to the bailout location)
  230. */
  231. void hs_dorestart(struct s_hc *hc, int filenum, long offset, int msgnum, int abort)
  232. {
  233. char str[20];
  234. register struct s_ftbl FAR *ft;
  235. int cnt;
  236. long fsize;
  237. HS_XMIT_CLEAR(hc); /* clear any pending data waiting for transmission */
  238. omsg_setnum(hc, -1);/* restart numbering */
  239. omsg_new(hc, 'R'); /* start a special 'R'estart message */
  240. #if FALSE
  241. hc->usecrc = (h_chkt == H_CRC || hc->sc.rmtchkt == H_CRC);
  242. #endif
  243. hc->usecrc = ((hc->h_chkt == H_CRC) || (hc->sc.rmtchkt == H_CRC));
  244. wsprintf(str, "R%c;T%d", tochar(msgnum), hc->usecrc ? H_CRC : H_CHECKSUM);
  245. omsg_add(hc, str);
  246. /* if we're backing up to an earlier point, tell receiver what blocksize
  247. * to use and verify the file number and offset
  248. */
  249. if (!abort && filenum > 0)
  250. {
  251. /* since the transfer is not error-free, retreat to min. blocksize */
  252. hc->blocksize = H_MINBLOCK;
  253. // StrFmt(str, "B%d;f%d;o%lu", hc->blocksize, filenum, offset);
  254. wsprintf(str, "B%d;f%d;o%lu", hc->blocksize, filenum, offset);
  255. omsg_add(hc, str);
  256. }
  257. omsg_send(hc, 1, TRUE, FALSE);
  258. /* find the requested file in the file table */
  259. while(hc->sc.ft_current >= 0)
  260. {
  261. if (hc->sc.hs_ftbl[hc->sc.ft_current].filen == filenum)
  262. break;
  263. --hc->sc.ft_current;
  264. }
  265. /* if we couldn't find the requested file in the file table it's
  266. Trouble with a capital 'T' */
  267. if (hc->sc.ft_current < 0)
  268. {
  269. hsdsp_event(hc, HSE_ILLEGAL);
  270. longjmp(hc->sc.jb_bailout, TSC_BAD_FORMAT);
  271. }
  272. ft = &hc->sc.hs_ftbl[hc->sc.ft_current]; /* set local ptr. into table for speed */
  273. hc->current_filen = filenum;
  274. /* Check that we're not stuck on an unresolvable problem. Twenty-five
  275. * consecutive requests to restart at the same place means the transfer
  276. * isn't ever likely to succeed. Probably caused by something like
  277. * an intermediate device stripping characters out.
  278. */
  279. if (hc->sc.lasterr_offset == offset && hc->sc.lasterr_filenum == filenum)
  280. {
  281. if (++hc->sc.sameplace >= 25)
  282. {
  283. ft->status = TSC_ERROR_LIMIT;
  284. hsdsp_event(hc, HSE_ERRLIMIT);
  285. longjmp(hc->sc.jb_bailout, TSC_ERROR_LIMIT);
  286. }
  287. }
  288. else
  289. {
  290. hc->sc.lasterr_offset = offset;
  291. hc->sc.lasterr_filenum = filenum;
  292. hc->sc.sameplace = 0;
  293. }
  294. if (abort && ft->status == TSC_OK) /* aborting current file ? */
  295. ft->status = TSC_RMT_CANNED;
  296. if (hc->ucancel || hc->sc.rmtcancel) /* received restart while trying
  297. to cancel */
  298. for (cnt = hc->sc.ft_current; cnt <= hc->sc.ft_top; ++cnt)
  299. {
  300. hc->sc.hs_ftbl[cnt].status =
  301. (int)(hc->ucancel ? TSC_USER_CANNED : TSC_RMT_CANNED);
  302. }
  303. /* if this isn't a simple backup operation, force the next character
  304. * read to return an EOF which will, in turn, force hs_filebreak to
  305. * be called to handle these more difficult situations
  306. */
  307. if (filenum == 0 || ft->status != TSC_OK)
  308. hc->sc.hs_ptrgetc = hs_reteof;
  309. else
  310. {
  311. /* reopen file if necessary */
  312. hc->h_filebytes = hc->sc.bytes_sent = offset;
  313. hc->total_dsp = ft->dsp_bytes;
  314. hc->total_thru = ft->thru_bytes;
  315. if (hc->sc.ft_current != hc->sc.ft_open)
  316. {
  317. if (hc->fhdl)
  318. fio_close(hc->fhdl);
  319. hc->fhdl = NULL;
  320. hc->sc.ft_open = hc->sc.ft_current;
  321. if (xfer_opensendfile(hc->hSession, &hc->fhdl, ft->fname, &fsize,
  322. NULL, NULL) != 0)
  323. {
  324. ft->status = TSC_CANT_OPEN;
  325. hc->sc.ft_open = -1;
  326. }
  327. hsdsp_newfile(hc, filenum, ft->fname, fsize);
  328. }
  329. if (ft->status == TSC_OK)
  330. {
  331. if (fio_seek(hc->fhdl, offset, FIO_SEEK_SET) == EOF)
  332. ft->status = TSC_DISK_ERROR;
  333. else
  334. {
  335. hc->sc.hs_ptrgetc = hs_getc;
  336. /* restart compression if necessary */
  337. if (bittest(ft->cntrl, FTC_COMPRESSED))
  338. {
  339. compress_start(&hc->sc.hs_ptrgetc,
  340. hc,
  341. &hc->h_filebytes,
  342. FALSE);
  343. hsdsp_compress(hc, ON);
  344. hsdsp_status(hc, HSS_SENDING);
  345. }
  346. else
  347. hsdsp_compress(hc, OFF);
  348. }
  349. }
  350. }
  351. hc->datacnt = 0;
  352. hc->h_checksum = hc->h_crc = 0;
  353. longjmp(hc->sc.jb_restart, 1);
  354. }
  355. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  356. * hs_background
  357. *
  358. * DESCRIPTION:
  359. * Called by the main transfer loops to handle asynchronous background tasks.
  360. * Specifically, the serial port is scanned for incoming messages from the
  361. * receiver. This routine also detects when the receiver has been silent too
  362. * long (and thus may be dead).
  363. *
  364. * ARGUMENTS:
  365. * none
  366. *
  367. * RETURNS:
  368. * nothing
  369. */
  370. void hs_background(struct s_hc *hc)
  371. {
  372. hs_rcvmsg(hc);
  373. if (xfer_user_interrupt(hc->hSession))
  374. {
  375. hsdsp_event(hc, HSE_USRCANCEL);
  376. if (hc->ucancel) /* this is the second time */
  377. longjmp(hc->sc.jb_bailout, TSC_USER_CANNED);
  378. else
  379. {
  380. hc->ucancel = TRUE;
  381. /* TODO: fix this somehow */
  382. /* errorline(FALSE, strld(TM_WAIT_CONF)); */
  383. hc->sc.hs_ptrgetc = hs_reteof; /* force sending to break */
  384. }
  385. }
  386. if (xfer_carrier_lost(hc->hSession))
  387. longjmp(hc->sc.jb_bailout, TSC_LOST_CARRIER);
  388. #if !defined(NOTIMEOUTS)
  389. if ((long)interval(hc->sc.last_response) > (hc->deadmantime * 2L + 100L))
  390. {
  391. hsdsp_event(hc, HSE_NORESP);
  392. longjmp(hc->sc.jb_bailout, TSC_NO_RESPONSE);
  393. }
  394. #endif
  395. xfer_idle(hc->hSession);
  396. }
  397. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  398. * hs_rcvmsg
  399. *
  400. * DESCRIPTION:
  401. * Called by hs_background to collect messages from the receiver piecemeal
  402. * and call hs_decode_rmsg when a complete message is assembled.
  403. *
  404. * ARGUMENTS:
  405. * none
  406. *
  407. * RETURNS:
  408. * nothing
  409. */
  410. #define IDLE -1
  411. #define AWAITING_TYPE -2
  412. #define AWAITING_LEN -3
  413. void hs_rcvmsg(struct s_hc *hc)
  414. {
  415. HCOM hCom;
  416. TCHAR cc;
  417. unsigned rm_checksum;
  418. BYTE *sp;
  419. hCom = sessQueryComHdl(hc->hSession);
  420. // while ((cc = RemoteGet()) != -1)
  421. while (mComRcvChar(hCom, &cc) != 0)
  422. {
  423. if ((*hc->dptr = (BYTE)cc) == H_MSGCHAR)
  424. {
  425. /* start receiving new message, even if last one hadn't finished */
  426. hc->rmcnt = AWAITING_TYPE + 1;
  427. hc->dptr = hc->msgdata;
  428. }
  429. // TODO: figure the correct way for this - else if (!isprint(*hc->dptr))
  430. else if ((*hc->dptr < 0x20) || (*hc->dptr > 0x7E))
  431. /* ignore other non-printing characters */;
  432. else
  433. {
  434. switch(--hc->rmcnt)
  435. {
  436. case IDLE:
  437. ++hc->rmcnt; /* so we'll still be idle next time */
  438. break;
  439. case AWAITING_TYPE:
  440. ++hc->dptr; /* keep type char. */
  441. hc->rmcnt = AWAITING_LEN + 1;
  442. break;
  443. case AWAITING_LEN:
  444. if ((hc->rmcnt = unchar(*hc->dptr)) < 3 || hc->rmcnt > 94)
  445. {
  446. hc->rmcnt = IDLE + 1;
  447. hc->dptr = hc->msgdata;
  448. }
  449. else
  450. ++hc->dptr;
  451. break;
  452. default:
  453. ++hc->dptr; /* just keep the char. */
  454. break;
  455. case 0: /* just received final char. of message */
  456. hc->rmcnt = IDLE + 1; /* start over with next char. */
  457. /* verify the checksum */
  458. --hc->dptr; /* point to first char of checksum */
  459. rm_checksum = 0;
  460. for (sp = hc->msgdata; sp < hc->dptr; ++sp)
  461. rm_checksum += *sp;
  462. /* sp now points to first check char */
  463. hc->dptr = hc->msgdata;
  464. if (*sp == tochar(rm_checksum & 0x3F) &&
  465. *(sp + 1) == tochar((rm_checksum >> 6) & 0x3F))
  466. {
  467. /* received valid message */
  468. hc->sc.last_response = (long)startinterval();
  469. if (unchar(hc->msgdata[2]) != (BYTE)hc->sc.lastmsgn)
  470. {
  471. /* new message */
  472. *sp = '\0';
  473. hc->sc.lastmsgn = unchar(hc->msgdata[2]);
  474. hs_decode_rmsg(hc, hc->msgdata);
  475. }
  476. }
  477. break;
  478. }
  479. }
  480. xfer_idle(hc->hSession);
  481. }
  482. xfer_idle(hc->hSession);
  483. }
  484. /************************* end of hpr_snd0.c ****************************/