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
836 lines
23 KiB
/* File: C:\WACKER\xfer\hpr_rcv1.c (Created: 24-Jan-1994)
|
|
* created from HAWIN source file
|
|
* hpr_rcv1.c -- Routines to implement HyperProtocol receiver.
|
|
*
|
|
* Copyright 1989,1993,1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 1 $
|
|
* $Date: 10/05/98 1:16p $
|
|
*/
|
|
// #define DEBUGSTR
|
|
|
|
#include <windows.h>
|
|
#include <setjmp.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <term\res.h>
|
|
#include <sys\types.h>
|
|
#include <sys\utime.h>
|
|
|
|
#include <tdll\stdtyp.h>
|
|
#include <tdll\mc.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\globals.h>
|
|
#include <tdll\file_io.h>
|
|
|
|
#if !defined(BYTE)
|
|
#define BYTE unsigned char
|
|
#endif
|
|
|
|
#include "cmprs.h"
|
|
#include "itime.h"
|
|
|
|
#include "xfr_dsp.h"
|
|
#include "xfr_todo.h"
|
|
#include "xfr_srvc.h"
|
|
|
|
#include "xfer.h"
|
|
#include "xfer.hh"
|
|
#include "xfer_tsc.h"
|
|
|
|
#include "hpr.h"
|
|
#include "hpr.hh"
|
|
#include "hpr_sd.hh"
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_decode_msg
|
|
*
|
|
* DESCRIPTION:
|
|
* Called when a complete message has been received to decode the fields
|
|
* of the message. Messages are composed of printable characters in one
|
|
* or more fields separated by semicolons. Each field within a message
|
|
* is considered to be independent of any others but fields are guaranteed
|
|
* to be examined left to right with a message. Fields containing badly
|
|
* formatted information generate an error but fields containing unrecognized
|
|
* data are ignored.
|
|
* Note also that certain message fields may prevent subsequent fields from
|
|
* being decoded. For instance, if a partial data block 'P' field indicates
|
|
* that the previous data block was no good, a restart will be requested
|
|
* immediately and any undecoded fields will be ignored.
|
|
*
|
|
* ARGUMENTS:
|
|
* mdata -- A pointer to the printable string that contains the message
|
|
* fields.
|
|
*
|
|
* RETURNS:
|
|
* A status code which can be one of:
|
|
* H_OK if all fields were decoded without incident
|
|
* H_BADMSGFMT if a field is of a recognized type but contains badly
|
|
* formatted data.
|
|
* H_NORESYNCH if a restart was needed as the result of a field but
|
|
* could not be completed.
|
|
* H_FILEERR if a file error occurred while processing a field
|
|
* H_COMPLETE if the end of transfer field was encountered.
|
|
*/
|
|
int hr_decode_msg(struct s_hc *hc, BYTE *mdata)
|
|
{
|
|
HCOM hCom;
|
|
BYTE *field;
|
|
BYTE mstr[20];
|
|
int result = H_OK, retval, HRE_code;
|
|
int i;
|
|
BYTE typecode;
|
|
struct st_rcv_open stRcv;
|
|
|
|
hCom = sessQueryComHdl(hc->hSession);
|
|
|
|
// field = _fstrtok(mdata, FstrScolon());
|
|
field = strtok(mdata, ";");
|
|
while (field != NULL)
|
|
{
|
|
switch(typecode = *field++)
|
|
{
|
|
case 'N' : /* number of files to expect */
|
|
if (!hc->rc.files_expected)
|
|
{
|
|
hc->rc.files_expected = (int)atol(field);
|
|
if (hc->rc.files_expected > 1 && hc->rc.single_file &&
|
|
!hr_cancel(hc, HRE_TOO_MANY))
|
|
return(H_BADMSGFMT); /* this may need a new status */
|
|
hrdsp_filecnt(hc, hc->rc.files_expected);
|
|
}
|
|
break;
|
|
|
|
case 'S' : /* size in bytes of all files */
|
|
if (hc->rc.bytes_expected == -1L)
|
|
{
|
|
if ((hc->rc.bytes_expected = atol(field)) <= 0)
|
|
hc->rc.bytes_expected = -1L;
|
|
else
|
|
hrdsp_totalsize(hc, hc->rc.bytes_expected);
|
|
}
|
|
break;
|
|
|
|
case 'A' : /* abort current file */
|
|
hrdsp_event(hc, HRE_RMTABORT);
|
|
if (hc->fhdl)
|
|
hr_closefile(hc, HRE_RMTABORT);
|
|
break;
|
|
|
|
case 'P' : /* check partial block */
|
|
if ((int)atol(field) != (hc->blocksize - hc->datacnt)
|
|
|| (field = strchr(field, ',')) == NULL
|
|
|| (unsigned)atol(field + 1)
|
|
!= (hc->usecrc ? hc->h_crc : hc->h_checksum))
|
|
if (!hr_restart(hc, HRE_DATAERR))
|
|
return(H_NORESYNCH);
|
|
hc->rc.checkpoint = hc->h_filebytes;
|
|
hc->datacnt = hc->blocksize;
|
|
hc->h_checksum = hc->h_crc = 0;
|
|
break;
|
|
|
|
case 'F' : /* new file */
|
|
if (hc->current_filen && hc->fhdl && !hr_closefile(hc, HRE_NONE))
|
|
return(H_FILEERR);
|
|
/* set up for new file */
|
|
hc->h_filebytes = hc->rc.checkpoint = 0L;
|
|
hc->rc.filesize = -1L;
|
|
hc->rc.ul_lstw = 0; /* don't know date/time */
|
|
if ((int)atol(field) != ++hc->current_filen ||
|
|
(field = strchr(field, ',')) == NULL)
|
|
return(H_BADMSGFMT);
|
|
strcpy(hc->rc.rmtfname, ++field);
|
|
hc->rc.filesize = -1L;
|
|
|
|
|
|
/* set up argument structure and let transfer open the file
|
|
*/
|
|
stRcv.pszSuggestedName = hc->rc.rmtfname;
|
|
stRcv.pszActualName = hc->rc.ourfname;
|
|
/* TODO: figure out how this time stuff works */
|
|
stRcv.lFileTime = hc->rc.ul_cmp;
|
|
|
|
// stRcv.pfnVscanOutput = hr_virus_detect;
|
|
// stRcv.pfnVscanOutput = (VOID (FAR *)(VOID FAR *, USHORT))hc->rc.pfVirusCheck;
|
|
// stRcv.ssmchVscanHdl = hc->rc.ssmchVscan;
|
|
|
|
if ((retval = xfer_open_rcv_file(hc->hSession, &stRcv, 0L)) != 0)
|
|
{
|
|
switch (retval)
|
|
{
|
|
case -6:
|
|
HRE_code = HRE_USER_REFUSED;
|
|
break;
|
|
case -5:
|
|
HRE_code = HRE_DISK_ERR;
|
|
break;
|
|
case -4:
|
|
HRE_code = HRE_NO_FILETIME;
|
|
break;
|
|
case -3:
|
|
HRE_code = HRE_CANT_OPEN;
|
|
break;
|
|
case -2:
|
|
HRE_code = HRE_OLDER_FILE;
|
|
break;
|
|
case -1:
|
|
default:
|
|
HRE_code = HRE_CANT_OPEN;
|
|
break;
|
|
}
|
|
|
|
if (!hr_cancel(hc, HRE_code))
|
|
return(H_FILEERR);
|
|
}
|
|
hc->fhdl = stRcv.bfHdl;
|
|
hc->rc.basesize = stRcv.lInitialSize;
|
|
|
|
// hc->rc.ssmchVscan = stRcv.ssmchVscanHdl;
|
|
// xferMsgVirusScan(hSession, (hc->rc.ssmchVscan == (SSHDLMCH)0) ? 0:1);
|
|
// hc->rc.virus_detected = FALSE;
|
|
|
|
hrdsp_compress(hc, FALSE);
|
|
hrdsp_newfile(hc, hc->current_filen, hc->rc.rmtfname, hc->rc.ourfname);
|
|
hc->datacnt = hc->blocksize;
|
|
hc->h_checksum = hc->h_crc = 0;
|
|
|
|
/* If there is no valid compare time, then the /N option is not
|
|
* being used or there is no existing file and we can set up to
|
|
* store received data. If there is a compare time, keep tossing
|
|
* characters until we've verified that the incoming file is
|
|
* newer than what we have.
|
|
*/
|
|
if (hc->rc.ul_cmp == (unsigned long)(-1))
|
|
hc->rc.hr_ptr_putc = hr_toss;
|
|
//else if (hc->rc.ssmchVscan == (SSHDLMCH)0)/* is virscan active? */
|
|
// hc->rc.hr_ptr_putc = hr_putc;
|
|
// else
|
|
//hc->rc.hr_ptr_putc = hr_putc_vir;
|
|
else
|
|
hc->rc.hr_ptr_putc = hr_putc;
|
|
|
|
break;
|
|
|
|
case 'V' : /* Version identifier from sender */
|
|
i = (int)atol(field);
|
|
if ((field = strchr(field, ',')) == NULL)
|
|
return(H_BADMSGFMT);
|
|
|
|
/* if version restrictions were found, stop the transfer */
|
|
if (hpr_id_check(hc, i, ++field))
|
|
break;
|
|
/* else fall through */
|
|
|
|
case 'X' :
|
|
if (hc->rc.cancel_reason == HRE_NONE)
|
|
hc->rc.cancel_reason = HRE_RMTABORT;
|
|
hrdsp_event(hc, hc->rc.cancel_reason);
|
|
/* fall through */
|
|
|
|
case 'E' : /* end of transfer */
|
|
omsg_new(hc, 'c');
|
|
// StrFmt(mstr, "E%d", hc->current_filen + 1);
|
|
wsprintf(mstr, "E%d", hc->current_filen + 1);
|
|
omsg_add(hc, mstr);
|
|
// RemoteClear(); /* get rid of any prod messages */
|
|
ComRcvBufrClear(hCom);
|
|
|
|
/* Sending the next message as a burst causes the excess characters
|
|
* to be sent to the remote system after the transfer has ended,
|
|
* perhaps causing them to dither on the display. It is tempting
|
|
* to send a single message rather that a burst, but the receiver
|
|
* is going to assume the transfer is done and exit after sending
|
|
* this message so there is no chance for an error recovery if
|
|
* the message is hit.
|
|
*/
|
|
omsg_send(hc, BURSTSIZE, FALSE, TRUE);
|
|
hc->xfertime = interval(hc->xfertimer);
|
|
hrdsp_status(hc, typecode == 'E' ? HRS_COMPLETE : HRS_CANCELLED);
|
|
if (hc->current_filen > 0 && hc->fhdl)
|
|
{
|
|
if (typecode == 'E')
|
|
{
|
|
if (!hr_closefile(hc, HRE_NONE))
|
|
return(H_FILEERR);
|
|
}
|
|
else
|
|
hr_closefile(hc, hc->rc.cancel_reason);
|
|
}
|
|
return(H_COMPLETE);
|
|
|
|
case 'C' :
|
|
if (strlen(field) == 0 &&
|
|
!decompress_start(&hc->rc.hr_ptr_putc, hc, FALSE))
|
|
{
|
|
result = H_FILEERR;
|
|
}
|
|
else
|
|
{
|
|
hrdsp_compress(hc, TRUE);
|
|
hc->rc.using_compression = TRUE;
|
|
hrdsp_status(hc, HRS_REC);
|
|
}
|
|
break;
|
|
|
|
case 's' :
|
|
if ((hc->rc.filesize = atol(field)) > 0)
|
|
hrdsp_filesize(hc, hc->rc.filesize);
|
|
break;
|
|
|
|
case 't' : /* file time/date */
|
|
{
|
|
unsigned long ulTime;
|
|
struct tm stT;
|
|
|
|
memset(&stT, 0, sizeof(struct tm));
|
|
stT.tm_year = atoi(field); /* ?? adjust */
|
|
if ((field = strchr(field, ',')) != NULL)
|
|
stT.tm_mon = atoi(++field);
|
|
if (field != NULL && (field = strchr(field, ',')) != NULL)
|
|
stT.tm_mday = atoi(++field);
|
|
if (field != NULL && (field = strchr(field, ',')) != NULL)
|
|
stT.tm_hour = atoi(++field);
|
|
if (field != NULL && (field = strchr(field, ',')) != NULL)
|
|
stT.tm_min = atoi(++field);
|
|
if (field != NULL && (field = strchr(field, ',')) != NULL)
|
|
stT.tm_sec = atoi(++field);
|
|
|
|
ulTime = mktime(&stT);
|
|
if ((long)ulTime == (-1))
|
|
ulTime = 0;
|
|
else
|
|
ulTime -= itimeGetBasetime();
|
|
|
|
hc->rc.ul_lstw = ulTime;
|
|
|
|
/*
|
|
* if hc->rc.ul_cmp contains a valid date/time, it means that
|
|
* the /N options was used and the file being received already
|
|
* exists. Compare the two times and reject any file that is
|
|
* not newer than what we already have.
|
|
*/
|
|
if (hc->rc.ul_cmp != 0)
|
|
{
|
|
if (hc->rc.ul_cmp >= hc->rc.ul_lstw)
|
|
{
|
|
/* reject incoming file */
|
|
hr_reject_file(hc, HRE_OLDER_FILE);
|
|
hc->rc.ul_cmp = (unsigned long)(-1);
|
|
}
|
|
else
|
|
{
|
|
/* everything is OK */
|
|
// if (hc->rc.ssmchVscan == (SSHDLMCH)0)
|
|
hc->rc.hr_ptr_putc = hr_putc; /* no virus checking */
|
|
// else
|
|
// hc->rc.hr_ptr_putc = hr_putc_vir; /* use vir check */
|
|
hc->rc.ul_cmp = 0;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'B' :
|
|
hc->blocksize = (int)atol(field);
|
|
break;
|
|
|
|
case 'D' :
|
|
hc->deadmantime = atol(field) * 10;
|
|
break;
|
|
|
|
case 'I' :
|
|
hr_still_alive(hc, TRUE, FALSE);
|
|
break;
|
|
|
|
case 'T' :
|
|
if ((i = (int)atol(field)) == 1)
|
|
hc->usecrc = FALSE;
|
|
else if (i == 2)
|
|
hc->usecrc = TRUE;
|
|
else
|
|
result = H_BADMSGFMT;
|
|
break;
|
|
|
|
default:
|
|
/* ignore, might be option supported in later version */
|
|
break;
|
|
}
|
|
// field = _fstrtok(NULL, FstrScolon());
|
|
field = strtok(NULL, ";");
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_reject_file
|
|
*
|
|
* DESCRIPTION:
|
|
* Called when we are trying to reject a file that we are receiving.
|
|
*
|
|
* ARGUEMENTS:
|
|
* reason -- why we are rejecting the file
|
|
*
|
|
* RETURNS:
|
|
* Always TRUE
|
|
*/
|
|
int hr_reject_file(struct s_hc *hc, int reason)
|
|
{
|
|
BYTE mstr[20];
|
|
|
|
/* reject incoming file */
|
|
omsg_new(hc, 'c');
|
|
wsprintf(mstr, "A%d", hc->current_filen);
|
|
omsg_add(hc, mstr);
|
|
omsg_send(hc, BURSTSIZE, FALSE, TRUE);
|
|
hrdsp_event(hc, reason);
|
|
hr_closefile(hc, reason);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_closefile
|
|
*
|
|
* DESCRIPTION:
|
|
* Called when the receiver is through saving to a particular file prior
|
|
* to switching to another file or finishing the transfer.
|
|
*
|
|
* ARGUMENTS:
|
|
* reason -- an event code indicating why this file is being closed
|
|
*
|
|
* RETURNS:
|
|
* TRUE if file is closed without problem.
|
|
* FALSE if an error occurred while closing.
|
|
*/
|
|
int hr_closefile(struct s_hc *hc, int reason)
|
|
{
|
|
int retcode;
|
|
|
|
hrdsp_progress(hc, FILE_DONE);
|
|
hc->total_thru += hc->h_filebytes;
|
|
hc->total_dsp += ((hc->rc.filesize == -1) ? hc->h_filebytes : hc->rc.filesize);
|
|
if (hc->fhdl != NULL)
|
|
{
|
|
// retcode = transfer_close_rcv_file(hc->fhdl, hr_result_codes[reason],
|
|
retcode = xfer_close_rcv_file(hc->hSession,
|
|
hc->fhdl,
|
|
hr_result_codes[reason],
|
|
hc->rc.rmtfname,
|
|
hc->rc.ourfname,
|
|
xfer_save_partial(hc->hSession),
|
|
hc->h_filebytes + hc->rc.basesize,
|
|
hc->h_useattr ? hc->rc.ul_lstw : 0L);
|
|
}
|
|
|
|
hc->fhdl = NULL;
|
|
hc->h_filebytes = 0;
|
|
hc->rc.using_compression = FALSE;
|
|
hc->rc.hr_ptr_putc = hr_toss;
|
|
return retcode;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_cancel
|
|
*
|
|
* DESCRIPTION:
|
|
* This routine is called when a problem or interruption during receiving
|
|
* forces a cancellation of the transfer. This routine attempts to inform
|
|
* the sender of the cancellation so that a graceful shutdown can be
|
|
* accomplished.
|
|
* It is up to the sender to actually shut down the transfer. We just send
|
|
* an interruption message to the sender asking him to do so.
|
|
*
|
|
* ARGUMENTS:
|
|
* reason -- A code providing the reason we must cancel. The reason codes
|
|
* are the same as the receiver event codes defined in the header
|
|
* file as HRE_*****
|
|
*
|
|
* RETURNS:
|
|
* TRUE if the sender responded to our request within a reasonable time.
|
|
* FALSE if the sender did not respond.
|
|
*
|
|
*/
|
|
int hr_cancel(struct s_hc *hc, int reason)
|
|
{
|
|
HCOM hCom;
|
|
BYTE str[40];
|
|
|
|
hCom = sessQueryComHdl(hc->hSession);
|
|
|
|
if (hc->rc.cancel_reason == HRE_NONE)
|
|
hc->rc.cancel_reason = reason;
|
|
|
|
if (reason == HRE_LOST_CARR)
|
|
return FALSE;
|
|
|
|
omsg_new(hc, 'c');
|
|
// StrFmt(str, "X;R%d,%lu", hc->current_filen, hc->rc.checkpoint);
|
|
wsprintf(str, "X;R%d,%lu", hc->current_filen, hc->rc.checkpoint);
|
|
|
|
DbgOutStr("%s\r\n", (LPSTR)str, 0,0,0,0);
|
|
|
|
omsg_add(hc, str);
|
|
hc->rc.hr_ptr_putc = hr_toss;
|
|
// RemoteClear();
|
|
ComRcvBufrClear(hCom);
|
|
hc->h_filebytes = hc->rc.checkpoint;
|
|
omsg_send(hc, BURSTSIZE, FALSE, FALSE);
|
|
return(hr_resynch(hc, reason));
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_restart
|
|
*
|
|
* DESCRIPTION:
|
|
* This routine is called when an error in the received data forces us
|
|
* to restart the transfer at the last known good location. This routine
|
|
* formats the interruption request message to the sender, sends the first
|
|
* message, then passes control to hr_resynch to figure out when and if
|
|
* the sender responds.
|
|
*
|
|
* ARGUMENTS:
|
|
* reason -- A code indicating the reason for the restart. The codes used
|
|
* are the receiver event codes itemized in the header file as
|
|
* HRE_*****
|
|
*
|
|
* RETURNS:
|
|
* TRUE if sender responds to the restart request.
|
|
* FALSE if the sender does not respond within a reasonable time.
|
|
*/
|
|
int hr_restart(struct s_hc *hc, int reason)
|
|
{
|
|
HCOM hCom;
|
|
BYTE str[15];
|
|
|
|
hCom = sessQueryComHdl(hc->hSession);
|
|
|
|
omsg_new(hc, 'c');
|
|
// StrFmt(str, "R%d,%lu", hc->current_filen, hc->rc.checkpoint);
|
|
wsprintf(str, "R%d,%lu", hc->current_filen, hc->rc.checkpoint);
|
|
omsg_add(hc, str);
|
|
// RemoteClear();
|
|
ComRcvBufrClear(hCom);
|
|
|
|
/* Don't start accepting characters if file is being rejected due to
|
|
* /N option and there is a file open to receive them.
|
|
*/
|
|
if ((hc->rc.ul_cmp == (unsigned long)(-1)) && (hc->fhdl != NULL))
|
|
// hc->rc.hr_ptr_putc = (hc->rc.ssmchVscan == (SSHDLMCH)0) ? hr_putc : hr_putc_vir;
|
|
hc->rc.hr_ptr_putc = hr_putc;
|
|
else
|
|
hc->rc.hr_ptr_putc = hr_toss;
|
|
|
|
if (hc->rc.using_compression)
|
|
decompress_start(&hc->rc.hr_ptr_putc, hc, FALSE);
|
|
hc->h_filebytes = hc->rc.checkpoint;
|
|
omsg_send(hc, BURSTSIZE, FALSE, FALSE);
|
|
if (hc->fhdl)
|
|
{
|
|
fio_seek(hc->fhdl,
|
|
(long)hc->rc.checkpoint + hc->rc.basesize,
|
|
FIO_SEEK_SET);
|
|
}
|
|
return(hr_resynch(hc, reason));
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_resynch
|
|
*
|
|
* DESCRIPTION:
|
|
* Attempts to resynchronize the receiver with the data stream coming
|
|
* from the sender. This routine is called when the receiver starts or
|
|
* after any interruption where the receiver asked the sender to restart
|
|
* its sending from a new location. The calling routine will have already
|
|
* sent the first copy of the restart message to the sender. This routine
|
|
* will monitor all messages arriving from the sender, looking for a
|
|
* restart message that matches the last request sent out. This routine
|
|
* will resend the restart request message at intervals to account for
|
|
* possible data loss or error in either the receiver message or the
|
|
* response from the sender.
|
|
*
|
|
* ARGUMENTS:
|
|
* hSession -- The session handle
|
|
* reason -- A reason code describing why the resynch must be performed.
|
|
* This will be HRE_NONE only in the case of initial startup.
|
|
*
|
|
* RETURNS:
|
|
* TRUE if resynch was successful.
|
|
* FALSE if resynch failed
|
|
*/
|
|
int hr_resynch(struct s_hc *hc, int reason)
|
|
{
|
|
HCOM hCom;
|
|
int fStarted = FALSE;
|
|
int tries = 0;
|
|
int try_limit = 0;
|
|
int request_again = FALSE; /* first request already made */
|
|
int result, i, j;
|
|
int iret;
|
|
// long l;
|
|
long timer, time_limit;
|
|
TCHAR rcode;
|
|
int mtype;
|
|
BYTE *msgdata;
|
|
BYTE *field;
|
|
int ok;
|
|
struct
|
|
{
|
|
int msgn;
|
|
long time;
|
|
} request_tbl[MAX_START_TRIES];
|
|
/* this variable is not accessed if NOTIMEOUTS is on */
|
|
long tmptime; /*lint -esym(550,tmptime)*/
|
|
|
|
hCom = sessQueryComHdl(hc->hSession);
|
|
|
|
// reason will be HRE_NONE only if this is the initial resynch call
|
|
// so we will set fStarted appropriately and use it to control behavior
|
|
// later on
|
|
if (reason == HRE_NONE)
|
|
{
|
|
fStarted = FALSE;
|
|
try_limit = MAX_START_TRIES;
|
|
}
|
|
else
|
|
{
|
|
fStarted = TRUE;
|
|
try_limit = MAXRETRIES;
|
|
hrdsp_event(hc, reason);
|
|
hrdsp_status(hc, HRS_REQRESYNCH);
|
|
++hc->total_tries;
|
|
hrdsp_errorcnt(hc, hc->total_tries);
|
|
}
|
|
// time_limit = RESYNCH_TIME; // MOBIDEM
|
|
j = hc->h_resynctime;
|
|
j *= 10;
|
|
if (j == 0)
|
|
j = RESYNCH_TIME;
|
|
time_limit = j;
|
|
|
|
request_tbl[0].msgn = omsg_number(hc);
|
|
timer = request_tbl[0].time = startinterval();
|
|
DbgOutStr("Initial:%d, %ld, %ld\r\n",
|
|
request_tbl[0].msgn, timer, time_limit, 0, 0);
|
|
for ( ; ; )
|
|
{
|
|
if (request_again)
|
|
{
|
|
if (++tries >= try_limit)
|
|
{
|
|
hrdsp_status(hc, HRS_CANCELLED);
|
|
if (hc->rc.cancel_reason == HRE_NONE)
|
|
hc->rc.cancel_reason = HRE_RETRYERR;
|
|
return(FALSE);
|
|
}
|
|
if (fStarted)
|
|
omsg_send(hc, BURSTSIZE, FALSE, FALSE);
|
|
else
|
|
omsg_send(hc, 1, FALSE, TRUE);
|
|
|
|
// Record this attempt in the table so we can match up responses
|
|
request_tbl[tries].msgn = omsg_number(hc);
|
|
timer = request_tbl[tries].time = startinterval();
|
|
++hc->total_tries;
|
|
hrdsp_errorcnt(hc, hc->total_tries);
|
|
request_again = FALSE;
|
|
DbgOutStr("Restart:%d, %0ld, %0ld\r\n",
|
|
request_tbl[tries].msgn, timer, time_limit, 0, 0);
|
|
}
|
|
|
|
iret = xfer_user_interrupt(hc->hSession);
|
|
if (iret == XFER_ABORT)
|
|
{
|
|
if (!fStarted || hc->ucancel)
|
|
return(FALSE);
|
|
else
|
|
{
|
|
return(hr_cancel(hc, HRE_USRCANCEL));
|
|
}
|
|
}
|
|
else if (iret == XFER_SKIP)
|
|
{
|
|
hr_reject_file(hc, HRE_USER_SKIP);
|
|
}
|
|
|
|
if (xfer_carrier_lost(hc->hSession))
|
|
return hr_cancel(hc, HRE_LOST_CARR);
|
|
|
|
#if !defined(NOTIMEOUTS)
|
|
if ((tmptime = interval(timer)) > time_limit)
|
|
{
|
|
request_again = TRUE;
|
|
if (fStarted)
|
|
// time_limit += RESYNCH_INC; // MOBIDEM
|
|
{
|
|
j = hc->h_resynctime;
|
|
j *= 10;
|
|
if (j == 0)
|
|
j = RESYNCH_INC;
|
|
time_limit += j;
|
|
}
|
|
hrdsp_event(hc, HRE_NORESP);
|
|
}
|
|
else
|
|
#endif
|
|
if (mComRcvChar(hCom, &rcode) == 0)
|
|
xfer_idle(hc->hSession);
|
|
else if (rcode == H_MSGCHAR)
|
|
{
|
|
/* restart messages always start with #0 & use CRC */
|
|
hc->rc.expected_msg = 0;
|
|
hc->usecrc = TRUE;
|
|
mtype = ' ';
|
|
result = hr_collect_msg(hc, &mtype, &msgdata, H_CHARTIME);
|
|
if (result == HR_KBDINT)
|
|
{
|
|
if (hc->ucancel)
|
|
return(FALSE);
|
|
else
|
|
{
|
|
hr_kbdint(hc);
|
|
return(hr_cancel(hc, HRE_USRCANCEL));
|
|
}
|
|
}
|
|
|
|
else if (result == HR_LOST_CARR)
|
|
return hr_cancel(hc, HRE_LOST_CARR);
|
|
|
|
else if (result != HR_COMPLETE) /* HR_TIMEOUT or HR_BAD??? */
|
|
{
|
|
DbgOutStr("Bad message\r\n", 0,0,0,0,0);
|
|
if (mtype == 'R') /* probably our resynch, try again */
|
|
{
|
|
DbgOutStr("Bad message was type R\r\n", 0,0,0,0,0);
|
|
hrdsp_event(hc, HRE_RETRYERR);
|
|
request_again = TRUE;
|
|
}
|
|
}
|
|
else if (mtype == 'R') /* good Resynch message */
|
|
{
|
|
if (!fStarted)
|
|
hc->xfertimer = startinterval();
|
|
fStarted = TRUE;
|
|
field = strtok(msgdata, ";");
|
|
if (field == NULL || *field++ != 'R')
|
|
{
|
|
DbgOutStr("Bad format\r\n", 0,0,0,0,0);
|
|
request_again = TRUE;
|
|
hrdsp_event(hc, HRE_ILLEGAL);
|
|
}
|
|
else
|
|
{
|
|
if (unchar(*field) != (BYTE)request_tbl[tries].msgn)
|
|
{
|
|
for (i = tries - 1; i >= 0; --i)
|
|
if (unchar(*field) == (BYTE)request_tbl[i].msgn)
|
|
{
|
|
// We got a response to an earlier restart request.
|
|
// Adjust the amount of time we wait for responses
|
|
// based on the actual time of the message just
|
|
// received.
|
|
|
|
// time_limit = interval(request_tbl[i].time) +
|
|
// RESYNCH_INC; // MOBIDEM
|
|
j = hc->h_resynctime;
|
|
j *= 10;
|
|
if (j == 0)
|
|
j = RESYNCH_INC;
|
|
time_limit = interval(request_tbl[i].time) + j;
|
|
|
|
DbgOutStr("Got %d, new time_limit=%ld\r\n",
|
|
request_tbl[i].msgn, time_limit, 0,0,0);
|
|
break; /* don't ask for retry */
|
|
}
|
|
if (i < 0)
|
|
{
|
|
hrdsp_event(hc, HRE_RETRYERR);
|
|
request_again = TRUE;
|
|
DbgOutStr("Not in table\r\n", 0,0,0,0,0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ok = TRUE;
|
|
// field = _fstrtok(NULL, FstrScolon());
|
|
field = strtok(NULL, ";");
|
|
while (field != NULL)
|
|
{
|
|
switch (*field++)
|
|
{
|
|
case 'f':
|
|
if ((int)atol(field) != hc->current_filen)
|
|
ok = FALSE;
|
|
break;
|
|
case 'o':
|
|
if (atol(field) != hc->rc.checkpoint)
|
|
ok = FALSE;
|
|
break;
|
|
case 'B':
|
|
hc->blocksize = (int)atol(field);
|
|
break;
|
|
case 'T' :
|
|
if ((i = (int)atol(field)) == 1)
|
|
hc->usecrc = FALSE;
|
|
else if (i == 2)
|
|
hc->usecrc = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
// field = _fstrtok(NULL, FstrScolon());
|
|
field = strtok(NULL, ";");
|
|
}
|
|
if (ok)
|
|
{
|
|
hc->h_checksum = hc->h_crc = 0;
|
|
hc->datacnt = hc->blocksize;
|
|
if (reason != HRE_NONE || tries > 0)
|
|
hrdsp_event(hc, HRE_ERRFIXED);
|
|
hrdsp_status(hc, HRS_REC);
|
|
DbgOutStr("Resynch successful\r\n", 0,0,0,0,0);
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
hrdsp_event(hc, HRE_RETRYERR);
|
|
request_again = TRUE;
|
|
DbgOutStr("Not OK\r\n", 0,0,0,0,0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*lint -unreachable*/
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_virus_detect
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
#if FALSE
|
|
STATICF VOID _export PASCAL hr_virus_detect(VOID FAR *h, USHORT usMatchId)
|
|
{
|
|
|
|
hc->rc.virus_detected = TRUE; /* force cancel of transfer */
|
|
}
|
|
#endif
|
|
|
|
|
|
/********************** end of hpr_rcv1.c ************************/
|