|
|
/* File: C:\WACKER\xfer\mdmx_rcv.c (Created: 18-Jan-1994)
* created from HAWIN source file * * mdmx_rcv.c -- XMODEM compatible file receiving routines for HA5G * * Copyright 1987,88,89,90,1994 by Hilgraeve Inc. -- Monroe, MI * All rights reserved * * $Revision: 9 $ * $Date: 7/11/02 3:58p $ */
#include <windows.h>
#pragma hdrstop
#include <stdlib.h>
// #include <setjmp.h>
#define BYTE unsigned char
#include <tdll\mc.h>
#include <tdll\stdtyp.h>
#include <tdll\com.h>
#include <tdll\assert.h>
#include <tdll\session.h>
#include <tdll\load_res.h>
#include <tdll\xfer_msc.h>
#include <tdll\file_io.h>
#include <tdll\htchar.h>
#include "xfr_srvc.h"
#include "xfr_todo.h"
#include "xfr_dsp.h"
#include "xfer_tsc.h"
#include "foo.h"
#include "cmprs.h"
#include "xfer.h"
#include "xfer.hh"
#include "mdmx.h"
#include "mdmx.hh"
#if !defined(STATIC_FUNC)
#define STATIC_FUNC
#endif
/* * * * * * * * * * * * *
* Function Prototypes * * * * * * * * * * * * * */
STATIC_FUNC void start_receive(ST_MDMX *xc, unsigned expect);
STATIC_FUNC int wait_receive(ST_MDMX *xc);
STATIC_FUNC int receivepckt(ST_MDMX *xc, HSESSION hSession, unsigned expect, struct s_mdmx_pckt *pckt);
STATIC_FUNC void respond(HSESSION hSession, ST_MDMX *xc, char code);
STATIC_FUNC void xm_clear_input(HSESSION hSession);
STATIC_FUNC void xm_rcheck(ST_MDMX *xc, HSESSION hSession, int before);
STATIC_FUNC void xm_check_input(HSESSION hSession, int suspend);
extern int xr_collect(ST_MDMX *, int, long, unsigned char **, unsigned char *, unsigned *);
/*lint -e502*/ /* lint seems to want the ~ operator applied
* only to unsigned, wer'e using uchar */ #define ESC_MSG_COL 1
/* * * * * * * * * * * *
* Shared Variables * * * * * * * * * * * * */
// int (NEAR *p_putc)(metachar c) = xm_putc;
// static struct s_mdmx_pckt *next_pckt;
// static unsigned this_pckt;
// static tiny check_type;
// static int batch;
// static int streaming;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* mdmx_rcv * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ int mdmx_rcv(HSESSION hSession, int attended, int method, int single_file) { ST_MDMX *xc; struct s_mdmx_pckt *last_pckt = NULL; struct s_mdmx_pckt *swap_pckt = NULL; struct st_rcv_open stRcv; TCHAR fname[FNAME_LEN]; TCHAR our_fname[FNAME_LEN]; long basesize; int still_trying = TRUE; int xpckt_size; int xstatus = TSC_OK; int override = FALSE; unsigned int uiOldOptions; unsigned tries, retries; unsigned char *cp; int blk_result = UNDEFINED, result = 0; char start_char; char nak_char;
TCHAR_Fill(fname, TEXT('\0'), FNAME_LEN);
/* allocate space for large packets since we don't necessarily know what
* we'll be getting. */ xc = NULL; last_pckt = NULL; xc = malloc(sizeof(ST_MDMX)); if (xc == NULL) goto done; memset(xc, 0, sizeof(ST_MDMX)); DbgOutStr("xc = 0x%x\r\n", xc, 0,0,0,0);
last_pckt = malloc(sizeof(ST_MDMX) + LARGE_PACKET + 2); if (last_pckt == NULL) goto done; memset(last_pckt, 0, sizeof(ST_MDMX));
xc->next_pckt = malloc(sizeof(ST_MDMX) + LARGE_PACKET + 2); if (xc->next_pckt == NULL) goto done; memset(xc->next_pckt, 0, sizeof(ST_MDMX));
xc->hSession = hSession; xc->hCom = sessQueryComHdl(hSession);
DbgOutStr("hs = 0x%x\r\n", hSession, 0,0,0,0);
mdmxXferInit(xc, method);
if (xfer_set_comport(hSession, FALSE, &uiOldOptions) != TRUE) goto done; else override = TRUE;
xc->file_bytes = 0L; xc->total_bytes = 0L; #if FALSE
xc->flagkey = kbd_register_flagkey(ESC_KEY, NULL); #endif
xc->fh = NULL; xc->xfertimer = -1L; xc->xfertime = 0L; xc->nfiles = 0; xc->filen = 0; xc->filesize = -1L; xc->nbytes = -1L;
still_trying = TRUE; blk_result = UNDEFINED; xc->batch = TRUE; xc->streaming = FALSE; start_char = 'C'; xc->check_type = CRC; mdmxdspChecktype(xc, (xc->check_type == CRC) ? 0 : 1); if (method == XF_YMODEM_G) { xc->streaming = TRUE; start_char = 'G'; } else if ((method == XF_XMODEM || method == XF_XMODEM_1K) && xc->mdmx_chkt == CHECKSUM) { start_char = NAK; xc->check_type = CHECKSUM; }
nak_char = start_char; xc->this_pckt = 0;
tries = 0; mdmxdspPacketErrorcnt(xc, tries);
retries = 0; mdmxdspErrorcnt(xc, retries);
xc->mdmx_byte_cnt = 0L;
mdmxdspChecktype(xc, (xc->check_type == CRC) ? 0 : 1);
start_receive(xc, xc->this_pckt); /* setup to receive first pckt */ if (attended) respond(hSession, xc, start_char);
while (still_trying) { blk_result = wait_receive(xc); switch(blk_result) { case NOBATCH_PCKT: /* Received pckt 1 while waiting for pckt 0.
* This must be an XMODEM as opposed to a YMODEM transfer */ if (!single_file) { xstatus = TSC_BAD_FORMAT; still_trying = FALSE; break; } xc->this_pckt = 1; xc->batch = FALSE; xc->filesize = -1L; nak_char = NAK;
stRcv.pszSuggestedName = ""; stRcv.pszActualName = our_fname; stRcv.lFileTime = 0;
result = xfer_open_rcv_file(hSession, &stRcv, 0L); if (result != 0) { switch (result) { case -6: xstatus = TSC_REFUSE; break; case -5: xstatus = TSC_CANT_OPEN; break; case -4: xstatus = TSC_NO_FILETIME; break; case -3: xstatus = TSC_CANT_OPEN; break; case -2: xstatus = TSC_OLDER_FILE; break; case -1: default: xstatus = TSC_CANT_OPEN; break; } still_trying = FALSE; break; }
xc->fh = stRcv.bfHdl; xc->basesize = stRcv.lInitialSize;
basesize = stRcv.lInitialSize;
mdmxdspNewfile(xc, 0, our_fname, our_fname);
/* fall through */ case ALT_PCKT: case GOOD_PCKT: /* swap pckt pointers so we can work on this one while receiving
* the next */ swap_pckt = last_pckt; last_pckt = xc->next_pckt; xc->next_pckt = swap_pckt; if (xc->this_pckt != 0) start_receive(xc, xc->this_pckt + 1);
if (!xc->streaming) respond(hSession, xc, ACK); /* send ACK as soon as possible */ /* then send burst for Xmodem pckt 1 */ if (xc->this_pckt == 0) { if (!*(last_pckt->bdata)) /* no more files? */ { xc->xfertime = (long)interval(xc->xfertimer); still_trying = FALSE; break; } else if (xc->filen > 0 && single_file) /* getting too many files? */ { xstatus = TSC_TOO_MANY; still_trying = FALSE; break; }
start_receive(xc, 1); respond(hSession, xc, start_char);
/* get info out of packet 0 and open file */ StrCharCopyN(fname, last_pckt->bdata, FNAME_LEN); for (cp = fname; *cp != '\0'; cp++) if (*cp == '/') *cp = '\\';
stRcv.pszSuggestedName = fname; stRcv.pszActualName = our_fname; stRcv.lFileTime = 0; xfer_build_rcv_name(hSession, &stRcv);
result = xfer_open_rcv_file(hSession, &stRcv, 0L); if (result != 0) { switch (result) { case -6: xstatus = TSC_REFUSE; break; case -5: xstatus = TSC_CANT_OPEN; break; case -4: xstatus = TSC_NO_FILETIME; break; case -3: xstatus = TSC_CANT_OPEN; break; case -2: xstatus = TSC_OLDER_FILE; break; case -1: default: xstatus = TSC_CANT_OPEN; break; } still_trying = FALSE; break; }
xc->fh = stRcv.bfHdl; xc->basesize = stRcv.lInitialSize;
basesize = stRcv.lInitialSize;
mdmxdspNewfile(xc, ++xc->filen, fname, our_fname);
/* accumlate last transfer total and start new counter */ xc->total_bytes += xc->file_bytes; xc->mdmx_byte_cnt = xc->file_bytes = 0L; xc->filesize = -1L; cp = last_pckt->bdata + StrCharGetByteCount(last_pckt->bdata) + 1; if (*cp) { xc->filesize = atol(cp);
mdmxdspFilesize(xc, xc->filesize); } nak_char = NAK; } else { /* unload packet data */ cp = last_pckt->bdata; xpckt_size = (last_pckt->start_char == STX ? LARGE_PACKET : SMALL_PACKET);
if (xs_unload(xc, cp, xpckt_size) == (-1) /* ERROR */ ) { xm_clear_input(hSession); respond(hSession, xc, CAN); xstatus = TSC_DISK_ERROR; still_trying = FALSE; break; }
// if (xc->filesize != -1L) jmh 03-08-96 to match HAWin
if (xc->filesize > 0) xc->file_bytes = min(xc->filesize, xc->mdmx_byte_cnt); else xc->file_bytes = xc->mdmx_byte_cnt; }
mdmxdspPacketnumber(xc, (long)++xc->this_pckt);
if (tries) mdmxdspPacketErrorcnt(xc, tries = 0);
mdmx_progress(xc, 0);
break;
case END_PCKT: /* the special EOT handling was removed from version 3.20
* due to problems with RBBS-PC. It should be modified and * reenabled after experimentation. */
respond(hSession, xc, ACK); /* ACK the EOT */ mdmx_progress(xc, FILE_DONE);
/* It's possible to get an unwanted EOT (if the ACK from the
* first EOT is lost) so we should treat it like a repeated * packet. */
if (xc->fh) /* if file was open */ { if (!xfer_close_rcv_file(hSession, xc->fh, xstatus, fname, our_fname, xfer_save_partial(hSession), xc->basesize + xc->file_bytes /*xc->filesize jmh 03-08-96*/, 0)) { xstatus = TSC_DISK_ERROR; still_trying = FALSE; break; }
xc->fh = NULL; }
if (!xc->batch) { xc->xfertime = (long)interval(xc->xfertimer); still_trying = FALSE; } else { start_receive(xc, xc->this_pckt = 0); respond(hSession, xc, nak_char = start_char); }
if (tries) // VidWrtStrF(xc->toprow + XR_DR_RETRIES, xc->dc_retries,
// "^H%-2d", tries = 0);
mdmxdspPacketErrorcnt(xc, tries = 0);
break;
case REPEAT_PCKT: start_receive(xc, xc->this_pckt); respond(hSession, xc, ACK); ++tries; break;
case WRONG_PCKT: xm_clear_input(hSession); respond(hSession, xc, CAN); ++tries; /* to get packet error on screen */ still_trying = FALSE; xstatus = TSC_OUT_OF_SEQ; break;
case SHORT_PCKT: case BAD_FORMAT: case BAD_CHECK: case NO_PCKT: ++tries; if (xc->mdmx_chkt == UNDETERMINED && xc->this_pckt == 0 && tries == 3 && method == XF_XMODEM) { xc->check_type = CHECKSUM; start_char = nak_char = NAK; // VidWrtStr(xc->toprow + XR_DR_ERR_CHK, xc->dc_err_chk,
// strld(TM_CHECKSUM));
mdmxdspChecktype(xc, 1); } xm_clear_input(hSession); respond(hSession, xc, nak_char); start_receive(xc, xc->this_pckt); break;
case BLK_ABORTED: xm_clear_input(hSession); respond(hSession, xc, CAN); xstatus = TSC_USER_CANNED; still_trying = FALSE; break;
case CARRIER_LOST: xm_clear_input(hSession); xstatus = TSC_LOST_CARRIER; still_trying = FALSE; break;
case CANNED: xm_clear_input(hSession); xstatus = TSC_RMT_CANNED; still_trying = FALSE; break;
default: // assert(FALSE);
break; }
if (tries) { mdmxdspPacketErrorcnt(xc, tries);
mdmxdspErrorcnt(xc, ++retries);
mdmxdspLastError(xc, blk_result);
if ((tries >= (unsigned)xc->mdmx_tries) || (xc->streaming && xc->this_pckt > 0)) { xm_clear_input(hSession); respond(hSession, xc, CAN); xstatus = TSC_ERROR_LIMIT; still_trying = FALSE; } } } /* while (still_trying) */
done:
if (xc) { if (xc->xfertime == 0L) { xc->xfertime = (long)interval(xc->xfertimer); }
mdmx_progress(xc, TRANSFER_DONE); }
if (override) { #if FALSE
cnfg.send_xprot = hld_send_xprot; cnfg.save_xprot = hld_save_xprot; cnfg.bits_per_char = hld_bits_per_char; cnfg.parity_type = hld_parity_type; (void)(*ComResetPort)(); #endif
xfer_restore_comport(hSession, uiOldOptions); }
if (xc) { if (xstatus != TSC_OK) { if (xc->fh) { xfer_close_rcv_file(hSession, xc->fh, xstatus, fname, our_fname, xfer_save_partial(hSession), xc->basesize + xc->file_bytes /*xc->filesize jmh 03-08-96*/, 0); } }
#if FALSE
kbd_deregister_flagkey(xc->flagkey); #endif
mdmxdspCloseDisplay(xc);
#if defined(DEADWOOD)
if (xc->p_crc_tbl != NULL) { resFreeDataBlock(xc->hSession, xc->p_crc_tbl); xc->p_crc_tbl = NULL; } #else // defined(DEADWOOD
//
// We don't need to free xc->p_crc_tbl since it is pointing
// to a static constant array. REV: 4/10/2002
//
xc->p_crc_tbl = NULL; #endif // defined(DEADWOOD)
if (xc->next_pckt) { free(xc->next_pckt); xc->next_pckt = NULL; }
free(xc); xc = NULL; }
if (last_pckt) { free(last_pckt); last_pckt = NULL; }
return((int)xstatus); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* start_receive * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ STATIC_FUNC void start_receive(ST_MDMX *xc, unsigned expect) { xc->next_pckt->result = UNDEFINED; xc->next_pckt->expected = expect; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* wait_receive * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ STATIC_FUNC int wait_receive(ST_MDMX *xc) { if (xc->next_pckt->result == UNDEFINED) { xc->next_pckt->result = receivepckt(xc, xc->hSession, xc->next_pckt->expected, xc->next_pckt); } return xc->next_pckt->result; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* receivepckt * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ STATIC_FUNC int receivepckt(ST_MDMX *xc, HSESSION hSession, unsigned expect, struct s_mdmx_pckt *pckt) { long timer, timeout; int gothdr = FALSE; int started = FALSE; TCHAR cc; unsigned char *cp; int gotCAN = FALSE; unsigned char checksum; unsigned crc; int count;
// DbgOutStr("pckt = 0x%x\r\n", pckt, 0,0,0,0);
timer = (long)startinterval();
/* wait for valid pckt-start character */ timeout = (long)(xc->mdmx_pckttime * 10);
while (!started) { #if FALSE
if (kbd_check_flagkey(xc->flagkey, TRUE)) { kbd_flush(); return(BLK_ABORTED); } #endif
if (xfer_carrier_lost(hSession)) return CARRIER_LOST;
if (xfer_user_interrupt(hSession)) { mdmxdspLastError(xc, BLK_ABORTED); return(BLK_ABORTED); }
mdmx_progress(xc, 0);
if ((long)interval(timer) > timeout) return(NO_PCKT);
// if ((cc = RemoteGet(hSession)) != -1)
if (mComRcvChar(xc->hCom, &cc) != 0) { DbgOutStr("pckt = 0x%x\r\n", pckt, 0,0,0,0); switch(pckt->start_char = (unsigned char)cc) { case EOT: if (xc->xfertimer == -1L) xc->xfertimer = (long)startinterval(); return(END_PCKT); /*lint -unreachable*/ break;
case SOH: case STX: started = TRUE; if (xc->xfertimer == -1L) xc->xfertimer = (long)startinterval(); break;
case CAN: /* if two consecutive CANs are received, drop out */ if (gotCAN) return(CANNED); gotCAN = TRUE; break;
default: /* ignore */ gotCAN = FALSE; /* two CANs must be consecutive */ break; } } else { xfer_idle(hSession, XFER_IDLE_IO); } } /* got valid start character, get packet numbers, data, & error codes */ timeout = xc->mdmx_chartime * 10; cp = &pckt->pcktnum; count = 2; for (;;) { if (!xr_collect(xc, count, timeout, &cp, &checksum, &crc)) return(SHORT_PCKT); if (!gothdr) { /* got pckt numbers, now get data and check code(s) */ gothdr = TRUE; count = (pckt->start_char == STX ? LARGE_PACKET : SMALL_PACKET); count += (xc->check_type == CRC ? 2 : 1); checksum = 0; crc = 0; cp = pckt->bdata; } else break; }
/* all bytes have been collected, check for valid packet */ if (xc->check_type == CHECKSUM) { /* at this point we've included the checksum itself in the checksum
* calculation. We need to back up, subtract the last char. from * the computation and use it for comparison instead. */ --cp; /* point to received checksum */ checksum = (unsigned char)(checksum - *cp); /* we added one too many */ if (checksum != *cp) return(BAD_CHECK); } else if (crc != 0) return(BAD_CHECK);
if (pckt->pcktnum != (unsigned char)((~pckt->npcktnum) & 0xFF)) { return(BAD_FORMAT); }
if (pckt->pcktnum != (unsigned char)(expect % 256)) { /* we always start out expecting ymodem batch, on an xmodem
* transfer, this code will detect the situation. */ if (!xc->filen && expect == 0 && pckt->pcktnum == 1) return NOBATCH_PCKT; else if (pckt->pcktnum == (unsigned char)((expect % 256) - 1)) return REPEAT_PCKT; /* repeated packets are harmless */ else return WRONG_PCKT; }
/* if we got this far, the pckt is good */ return(GOOD_PCKT); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* respond * * DESCRIPTION: * * ARGUMENTS: * * RETURNS: * */ STATIC_FUNC void respond(HSESSION hSession, ST_MDMX *xc, char code) /* wait for line to clear, then send code */ { int i;
ComSendChar(xc->hCom, &xc->stP, code); if (code == CAN) { for (i = 4 + 1; --i > 0; ) ComSendChar(xc->hCom, &xc->stP, CAN); } ComSendWait(xc->hCom, &xc->stP); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* xm_clear_input * * DESCRIPTION: * * * ARGUMENTS: * * * RETURNS: * */ STATIC_FUNC void xm_clear_input(HSESSION hSession) { // RemoteClear(hSession); /* make sure no junk is left sitting in it */
ComRcvBufrClear(sessQueryComHdl(hSession)); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* xm_rcheck * * DESCRIPTION: * * * ARGUMENTS: * * * RETURNS: * */ STATIC_FUNC void xm_rcheck(ST_MDMX *xc, HSESSION hSession, int before) { if (xc->streaming) { /* Do it different for YMODEM-G, since the sender won't wait for ACK */ #if FALSE
if (before) suspendinput(FLG_DISK_ACTIVE, 5); else allowinput(FLG_DISK_ACTIVE); #endif
} else { if (before) { /* wait till next packet is in before writing to disk */ if (xc->next_pckt->result == UNDEFINED) xc->next_pckt->result = wait_receive(xc); } } }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* xm_check_input * * DESCRIPTION: * * ARGUEMENTS: * * RETURNS: * */ STATIC_FUNC void xm_check_input(HSESSION hSession, int suspend) { }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* xr_collect * * DESCRIPTION: * * * ARGUMENTS: * * * RETURNS: * */ int xr_collect(ST_MDMX *xc, int count, long timeout, unsigned char **ptr, unsigned char *checksum, unsigned *crc) { unsigned char lchecksum; unsigned char *cp, *head; TCHAR rchar; int cnt; long timer;
head = cp = *ptr; lchecksum = *checksum; cnt = count;
while (cnt--) { // if ((rchar = RemoteGet(xc->hSession)) == -1)
if (mComRcvChar(xc->hCom, &rchar) == 0) { xfer_idle(xc->hSession, XFER_IDLE_IO); /* driver hasn't put any new chars in rmt_bufr */ timer = (long)startinterval(); // while ((rchar = RemoteGet(xc->hSession)) == -1)
while (mComRcvChar(xc->hCom, &rchar) == 0) { /* check for char timeout */ xfer_idle(xc->hSession, XFER_IDLE_IO); if ((long)interval(timer) > timeout) return(FALSE); } } *cp = (unsigned char)rchar; lchecksum += *cp; ++cp; } *ptr = cp; *checksum = lchecksum; if (count > 100) *crc = calc_crc(xc, (unsigned)0, head, count); return(TRUE); }
/***************************** end of mdmx_rcv.c **************************/
|