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.
719 lines
19 KiB
719 lines
19 KiB
/* File: C:\WACKER\xfer\hpr_rcv0.c (created: 24-Jun-1994)
|
|
* created from HAWIN source file:
|
|
* hpr_rcv0.c -- Routines to implement HyperProtocol receiver.
|
|
*
|
|
* Copyright 1989,1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 1 $
|
|
* $Date: 10/05/98 1:16p $
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <setjmp.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\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 "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"
|
|
|
|
/*
|
|
* not all event codes in this table are needed here, but having a complete
|
|
* table simplifies the lookup code substantially.
|
|
*/
|
|
int hr_result_codes[] = /* maps HyperProtocol event codes to result codes */
|
|
{
|
|
TSC_OK, /* HRE_NONE */
|
|
TSC_ERROR_LIMIT, /* HRE_DATAERR */
|
|
TSC_OUT_OF_SEQ, /* HRE_LOSTDATA */
|
|
TSC_NO_RESPONSE, /* HRE_NORESP */
|
|
TSC_ERROR_LIMIT, /* HRE_RETRYERR */
|
|
TSC_BAD_FORMAT, /* HRE_ILLEGAL */
|
|
TSC_OK, /* HRE_ERRFIXED */
|
|
TSC_RMT_CANNED, /* HRE_RMTABORT */
|
|
TSC_USER_CANNED, /* HRE_USRCANCEL */
|
|
TSC_NO_RESPONSE, /* HRE_TIMEOUT */
|
|
TSC_ERROR_LIMIT, /* HRE_DCMPERR */
|
|
TSC_LOST_CARRIER, /* HRE_LOST_CARR */
|
|
TSC_TOO_MANY, /* HRE_TOO_MANY */
|
|
TSC_DISK_FULL, /* HRE_DISK_FULL */
|
|
TSC_CANT_OPEN, /* HRE_CANT_OPEN */
|
|
TSC_DISK_ERROR, /* HRE_DISK_ERR */
|
|
TSC_OLDER_FILE, /* HRE_OLDER_FILE */
|
|
TSC_NO_FILETIME, /* HRE_NO_FILETIME */
|
|
TSC_VIRUS_DETECT, /* HRE_VIRUS_DET */
|
|
TSC_USER_SKIP, /* HRE_USER_SKIP */
|
|
TSC_REFUSE /* HRE_REFUSE */
|
|
};
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hpr_rcv
|
|
*
|
|
* DESCRIPTION:
|
|
* Receives files using the Hyperprotocol transfer method.
|
|
*
|
|
* ARGUMENTS:
|
|
* attended -- True if the program determines that a user is likely to be
|
|
* present at the computer keyboard. FALSE if a user is NOT
|
|
* likely to be present (such as host and script modes)
|
|
* single_file -- TRUE if user specified only a file name to receive the
|
|
* result of the transfer as opposed to naming a dirctory.
|
|
*
|
|
* RETURNS:
|
|
* TRUE if the transfer successfully completes. FALSE otherwise.
|
|
*/
|
|
int hpr_rcv(HSESSION hSession, int attended, int single_file)
|
|
{
|
|
struct s_hc *hc;
|
|
HCOM hCom;
|
|
int usRetVal;
|
|
int iret;
|
|
int status;
|
|
int result;
|
|
int timeout_cnt = 0;
|
|
int mtype;
|
|
BYTE *mdata;
|
|
char str[20];
|
|
long timer;
|
|
struct st_rcv_open stRcv;
|
|
BYTE tmp_name[FNAME_LEN];
|
|
|
|
hCom = sessQueryComHdl(hSession);
|
|
|
|
hc = malloc(sizeof(struct s_hc));
|
|
if (hc == NULL)
|
|
return TSC_NO_MEM;
|
|
|
|
memset(hc, 0, sizeof(struct s_hc));
|
|
|
|
hc->hSession = hSession;
|
|
|
|
/* initialize stuff */
|
|
if (!hr_setup(hc))
|
|
{
|
|
free(hc);
|
|
return TSC_NO_MEM;
|
|
}
|
|
|
|
/* initialize control variables */
|
|
|
|
/* blocksize depends on the speed of the connection. Larger block sizes
|
|
* can be used for faster connections. If the blocksize is too large,
|
|
* error detection will be slow. If too small, there is unnecessary overhead
|
|
*/
|
|
hc->blocksize = 2048;
|
|
// hc->blocksize = xfer_blocksize(hSession);
|
|
|
|
hc->current_filen = 0;
|
|
hc->datacnt = hc->blocksize;
|
|
hc->deadmantime = 600;
|
|
hc->total_tries = 0;
|
|
hc->total_thru = 0L;
|
|
hc->total_dsp = 0L;
|
|
hc->ucancel = FALSE;
|
|
hc->usecrc = TRUE; /* first messages in will use CRC */
|
|
hc->fhdl = NULL;
|
|
|
|
hc->rc.checkpoint = 0L;
|
|
hc->rc.files_expected = 0;
|
|
hc->rc.bytes_expected = -1L;
|
|
hc->rc.filesize = -1L;
|
|
hc->rc.expected_msg = 0;
|
|
hc->rc.cancel_reason = HRE_NONE;
|
|
hc->rc.using_compression = FALSE;
|
|
hc->rc.virus_detected = FALSE;
|
|
|
|
hc->rc.hr_ptr_putc = hr_toss;
|
|
hc->h_crc = hc->h_checksum = 0;
|
|
|
|
omsg_init(hc, TRUE, FALSE);
|
|
hc->rc.single_file = single_file; /* to the sender */
|
|
|
|
|
|
/* Receiver begins the transfer by transmitting a starting message
|
|
repeatedly until the sender begins */
|
|
|
|
/* prepare the initial message */
|
|
omsg_new(hc, 'c');
|
|
|
|
/* tell sender who we are */
|
|
hpr_id_get(hc, str);
|
|
omsg_add(hc, str);
|
|
|
|
/* we can express our opinion about what checktype and blocksize to use
|
|
* but it will be up to the sender to make the final choice
|
|
*/
|
|
wsprintf(str, "T%d", hc->h_chkt == H_CRC ? H_CRC : H_CHECKSUM);
|
|
omsg_add(hc, str);
|
|
|
|
wsprintf(str, "B%d", hc->blocksize);
|
|
omsg_add(hc, str);
|
|
|
|
/* let sender know whether we can handle compression */
|
|
if (hc->h_trycompress & compress_enable());
|
|
{
|
|
omsg_add(hc, "C");
|
|
}
|
|
|
|
/* A restart 0,0 request causes sender to start */
|
|
omsg_add(hc, "R0,0");
|
|
|
|
/* send first response packet at intervals until first H_MSGCHAR
|
|
* is received
|
|
*/
|
|
status = H_OK;
|
|
hrdsp_status(hc, HRS_REQSTART);
|
|
timer = startinterval();
|
|
|
|
stRcv.pszSuggestedName = "junk.jnk";
|
|
stRcv.pszActualName = tmp_name;
|
|
// stRcv.pstFtCompare = NULL;
|
|
stRcv.lFileTime = 0;
|
|
// stRcv.pfnVscanOutput = NULL;
|
|
// stRcv.ssmchVscanHdl = (SSHDLMCH)0;
|
|
|
|
// hc->rc.pfVirusCheck = MakeProcInstance((FARPROC)hr_virus_detect,
|
|
// hSession->hInstance);
|
|
|
|
// stRcv.pfnVscanOutput = (VOID (FAR *)(void *, int))hc->rc.pfVirusCheck;
|
|
|
|
// transfer_build_rcv_name(&stRcv);
|
|
xfer_build_rcv_name(hSession, &stRcv);
|
|
|
|
// hc->rc.ssmchVscan = stRcv.ssmchVscanHdl;
|
|
|
|
hc->xfertimer = -1;
|
|
|
|
#if FALSE
|
|
/* if we are the host, don't send an immediate start request because
|
|
* the user probably had to start us first and then set himself up. If
|
|
* we are the attended machine, though, the other end has probably already
|
|
* been started.
|
|
*/
|
|
// sendnext = (attended ? 0 : 40);
|
|
|
|
// Changed to always try to start immediately since we may be responding
|
|
// to auto-start in which case sender is already waiting
|
|
sendnext = 0;
|
|
|
|
repeat
|
|
{
|
|
hc->xfertimer = startinterval();
|
|
if (mComRcvBufrPeek(hCom, &rcode) != 0)
|
|
{
|
|
if (rcode == H_MSGCHAR)
|
|
{
|
|
if (!hr_resynch(hSession, HRE_NONE))
|
|
status = H_NOSTART;
|
|
break;
|
|
}
|
|
// RemoteGet(); /* wrong character, remove it from buffer */
|
|
mComRcvChar(hCom, &rcode);
|
|
|
|
/* Other end can send us an ESC to cancel the transfer before
|
|
* it ever gets started.
|
|
*/
|
|
if ((rcode == ESC) || (rcode == CAN))
|
|
{
|
|
status = H_RMTABORT;
|
|
hrdsp_event(hSession, hc->rc.cancel_reason = HRE_RMTABORT);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* We can't wait forever to get started. If we haven't seen a start
|
|
* character in H_START_WAIT seconds, give up.
|
|
*/
|
|
if ((time = interval(timer)) > H_START_WAIT * 10)
|
|
{
|
|
status = H_NOSTART;
|
|
hc->rc.cancel_reason = HRE_NORESP;
|
|
break;
|
|
}
|
|
|
|
/* see if it's time to send another startup request */
|
|
else if (time > sendnext || (rcode & 0x7F) == '\r')
|
|
{
|
|
sendnext = time + 40; /* send again in 4 seconds */
|
|
omsg_send(hc, 1, FALSE, TRUE);
|
|
}
|
|
|
|
/* finally, see if someone at keyboard want's us to stop trying */
|
|
iret = xfer_user_interrupt(hSession);
|
|
if (iret == XFER_ABORT)
|
|
{
|
|
status = H_USERABORT;
|
|
hrdsp_event(hSession, hc->rc.cancel_reason = HRE_USRCANCEL);
|
|
break;
|
|
}
|
|
else if (iret == XFER_SKIP)
|
|
{
|
|
hr_reject_file(hSession, HRE_USER_SKIP);
|
|
}
|
|
|
|
hpr_idle(hSession);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
omsg_send(hc, 1, FALSE, TRUE);
|
|
if (!hr_resynch(hc, HRE_NONE))
|
|
status = H_NOSTART;
|
|
|
|
/* If status is still H_OK, it means we've synched with sender.
|
|
* We'll stay in this loop now until the transfer is finished.
|
|
*/
|
|
while (status == H_OK)
|
|
{
|
|
hr_still_alive(hc, FALSE, FALSE); /* check whether deadman msg
|
|
is in order */
|
|
hrdsp_progress(hc, 0); /* keep user notified */
|
|
|
|
/* Collect blocks of data, which may be interrupted by messages
|
|
* from the sender.
|
|
*/
|
|
result = hr_collect_data(hc, &hc->datacnt, TRUE, H_CHARTIME);
|
|
if (result != HR_TIMEOUT)
|
|
timeout_cnt = 0;
|
|
switch(result)
|
|
{
|
|
case HR_VIRUS_FOUND:
|
|
goto virus_found;
|
|
|
|
case HR_COMPLETE:
|
|
/* got all chars. we asked for, setup to receive another
|
|
* full block
|
|
*/
|
|
hc->rc.checkpoint = hc->h_filebytes;
|
|
hc->h_checksum = hc->h_crc = 0;
|
|
hc->datacnt = hc->blocksize;
|
|
break;
|
|
|
|
case HR_DCMPERR :
|
|
/* data error caused decompression algorithm to fail */
|
|
if (!hr_restart(hc, HRE_DCMPERR))
|
|
status = H_NORESYNCH;
|
|
break;
|
|
|
|
case HR_BADCHECK :
|
|
/* got complete block but checksum or CRC didn't match */
|
|
if (!hr_restart(hc, HRE_DATAERR))
|
|
status = H_NORESYNCH;
|
|
break;
|
|
|
|
case HR_LOSTDATA :
|
|
/* received block n+1 before block n */
|
|
if (!hr_restart(hc, HRE_LOSTDATA))
|
|
status = H_NORESYNCH;
|
|
break;
|
|
|
|
case HR_MESSAGE:
|
|
/* Block of data was interrupted by a message. All that's
|
|
* actually been detected is a message character in the data,
|
|
* we must now extract and analyze the message
|
|
*/
|
|
switch(result = hr_collect_msg(hc, &mtype, &mdata, H_CHARTIME))
|
|
{
|
|
case HR_KBDINT:
|
|
/* local user interrupted us while receiving the message
|
|
* if user had interrupted us once and is doing it again
|
|
* while we are attempting to tell the other end what we're
|
|
* doing, drop out immediately and leave the sender to fend
|
|
* for himself.
|
|
*/
|
|
if (hc->ucancel)
|
|
status = H_USERABORT;
|
|
else
|
|
{
|
|
hr_kbdint(hc);
|
|
/* try to let sender know what we're doing */
|
|
if (!hr_cancel(hc, HRE_USRCANCEL))
|
|
status = H_USERABORT;
|
|
}
|
|
break;
|
|
|
|
case HR_TIMEOUT:
|
|
case HR_BADMSG:
|
|
case HR_BADCHECK:
|
|
/* message was scrambled, try to resynch */
|
|
if (!hr_restart(hc, HRE_DATAERR))
|
|
status = H_NORESYNCH;
|
|
break;
|
|
|
|
case HR_LOSTDATA:
|
|
/* message was recevied, but it was the wrong one */
|
|
if (!hr_restart(hc, HRE_LOSTDATA))
|
|
status = H_NORESYNCH;
|
|
break;
|
|
|
|
case HR_COMPLETE:
|
|
/* message received ok, figure out what sender wants */
|
|
status = hr_decode_msg(hc, mdata);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case HR_TIMEOUT:
|
|
/* sender stopped sending to us, try to prod him into restartting */
|
|
if (timeout_cnt++ < TIMEOUT_LIMIT)
|
|
{
|
|
/* TODO: generalize this
|
|
if (cnfg.save_xprot)
|
|
RemoteSendChar(cnfg.save_xon);
|
|
*/
|
|
hr_still_alive(hc, TRUE, TRUE); /* send file ack and timeout msg */
|
|
}
|
|
else
|
|
{
|
|
status = H_TIMEOUT;
|
|
hc->rc.cancel_reason = HRE_TIMEOUT;
|
|
}
|
|
break;
|
|
|
|
case HR_KBDINT:
|
|
/* user is trying to interrupt the transfer */
|
|
if (hc->ucancel)
|
|
status = H_USERABORT;
|
|
else
|
|
{
|
|
hr_kbdint(hc);
|
|
/* try to inform sender about what we are doing */
|
|
if (!hr_cancel(hc, HRE_USRCANCEL))
|
|
status = H_USERABORT;
|
|
}
|
|
break;
|
|
|
|
case HR_LOST_CARR:
|
|
/* we lost carrier while trying to transfer */
|
|
if (!hr_cancel(hc, HRE_LOST_CARR))
|
|
status = H_TIMEOUT;
|
|
break;
|
|
|
|
case HR_FILEERR:
|
|
/* A file error occurred while trying to save incoming data */
|
|
if (!hr_cancel(hc, HRE_DISK_ERR))
|
|
status = H_FILEERR;
|
|
break;
|
|
}
|
|
|
|
/* during full-bore transfers, the data collection routines won't
|
|
* waste time checking the keyboard for an interrupt request from
|
|
* the user or carrier loss so we'll check here at least once per
|
|
* data block
|
|
*/
|
|
iret = xfer_user_interrupt(hSession);
|
|
if (iret == XFER_ABORT)
|
|
{
|
|
if (hc->ucancel)
|
|
status = H_USERABORT;
|
|
else
|
|
{
|
|
hr_kbdint(hc);
|
|
if (!hr_cancel(hc, HRE_USRCANCEL))
|
|
status = H_USERABORT;
|
|
}
|
|
}
|
|
else if (iret == XFER_SKIP)
|
|
{
|
|
hr_reject_file(hc, HRE_USER_SKIP);
|
|
}
|
|
|
|
if (xfer_carrier_lost(hSession))
|
|
if (!hr_cancel(hc, HRE_LOST_CARR))
|
|
status = H_TIMEOUT;
|
|
|
|
/* Actual virus detection occurs deep in the bowels of a transfer.
|
|
* Therefore, the detecting routine merely sets a flag and begins
|
|
* tossing data. We actually shut down here
|
|
*/
|
|
virus_found:
|
|
if (hc->rc.virus_detected)
|
|
{
|
|
hc->rc.virus_detected = FALSE; /* don't come in here again */
|
|
if (!hr_cancel(hc, HRE_VIRUS_DET))
|
|
status = H_USERABORT;
|
|
}
|
|
}
|
|
|
|
/* Transfer is all done, 'status' indicates the final result. */
|
|
hrdsp_progress(hc, TRANSFER_DONE);
|
|
compress_disable();
|
|
|
|
// if (stRcv.ssmchVscanHdl != (SSHDLMCH)0)
|
|
// StrSrchStopSrch(stRcv.ssmchVscanHdl);
|
|
|
|
// if (hc->rc.pfVirusCheck != NULL)
|
|
// {
|
|
// FreeProcInstance(hc->rc.pfVirusCheck);
|
|
// hc->rc.pfVirusCheck = NULL;
|
|
// }
|
|
|
|
usRetVal = (int)hr_result_codes[hc->rc.cancel_reason];
|
|
|
|
/* clear display, free memory, etc. */
|
|
status = hr_wrapup(hc, attended, status);
|
|
free(hc);
|
|
|
|
return usRetVal;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_collect_msg
|
|
*
|
|
* DESCRIPTION:
|
|
* Called when a message has been detected within a block of data. Messages
|
|
* start with H_MSGCHAR (0x01). If an H_MSGCHAR occurs as part of the data
|
|
* being sent, it will be doubled. When it is encountered alone, this routine
|
|
* is called to extract the following message from the stream of data.
|
|
*
|
|
* ARGUMENTS:
|
|
* mtype -- pointer to a variable to be updated with the message type
|
|
* mdata -- pointer to a variable to be updated with the address of the
|
|
* message data
|
|
* timeout -- amount of time (in tenths of seconds) to wait for the data
|
|
* to complete the message.
|
|
*
|
|
* RETURNS:
|
|
* Returns a status code:
|
|
* HR_COMPLETE -- message successfully received
|
|
* HR_BADCHECK -- crc or checksum error on message data
|
|
* HR_TIMEOUT -- time out exceeded while waiting for data
|
|
* HR_KBDINT -- user interrupted from keyboard
|
|
* HR_BADMSG -- message data was not in recognized format
|
|
* HR_LOSTDATA -- message was complete but message number was not the
|
|
* expected one.
|
|
* HR_LOST_CARR --Lost carrier while collecting message
|
|
*/
|
|
// char FAR *storageptr; /* place to put data as we receive it */
|
|
|
|
int hr_collect_msg(struct s_hc *hc,
|
|
int *mtype,
|
|
BYTE **mdata,
|
|
long timeout)
|
|
{
|
|
unsigned hold_checksum;
|
|
unsigned hold_crc;
|
|
int gotlen = FALSE;
|
|
int count;
|
|
int result = HR_UNDECIDED;
|
|
int (*holdptr)(void *, int);
|
|
int msgn;
|
|
|
|
/* since a message is embedded within a data block, we need to preserve
|
|
* a few values for the interrupted data collection routine.
|
|
*/
|
|
holdptr = hc->rc.hr_ptr_putc;
|
|
/* set collection routine to store data for us */
|
|
hc->rc.hr_ptr_putc = hr_storedata;
|
|
hold_checksum = hc->h_checksum;
|
|
hold_crc = hc->h_crc;
|
|
hc->h_checksum = 0; /* messages have their own check bytes */
|
|
hc->h_crc = 0;
|
|
|
|
/* We will retrieve the message in two parts, first we'll get the type and
|
|
* length fields, then, based on those, we can collect the rest of the
|
|
* message.
|
|
*/
|
|
hc->storageptr = hc->rc.rmsg_bufr;
|
|
count = 2;
|
|
while (result == HR_UNDECIDED)
|
|
{
|
|
switch (result = hr_collect_data(hc, &count, FALSE, timeout))
|
|
{
|
|
case HR_COMPLETE:
|
|
if (!gotlen)
|
|
{
|
|
/* got first part, set up to get rest of message */
|
|
result = HR_UNDECIDED;
|
|
*mtype = hc->rc.rmsg_bufr[0];
|
|
count = hc->rc.rmsg_bufr[1];
|
|
if (count < 3)
|
|
result = HR_BADMSG;
|
|
gotlen = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* got everything, check for valid message */
|
|
msgn = hc->rc.rmsg_bufr[2];
|
|
count = hc->rc.rmsg_bufr[1];
|
|
if (hc->usecrc)
|
|
{
|
|
if (hc->h_crc != 0)
|
|
result = HR_BADCHECK;
|
|
}
|
|
else
|
|
{
|
|
hc->h_checksum -= hc->rc.rmsg_bufr[count];
|
|
hc->h_checksum -= hc->rc.rmsg_bufr[count + 1];
|
|
if (hc->rc.rmsg_bufr[count] != (BYTE)(hc->h_checksum % 256) ||
|
|
hc->rc.rmsg_bufr[count + 1] !=
|
|
(BYTE)(hc->h_checksum / 256))
|
|
result = HR_BADCHECK;
|
|
}
|
|
hc->rc.rmsg_bufr[count] = '\0';
|
|
}
|
|
break;
|
|
|
|
case HR_LOST_CARR:
|
|
case HR_TIMEOUT:
|
|
case HR_KBDINT:
|
|
/* return same result */
|
|
break;
|
|
|
|
case HR_MESSAGE:
|
|
/* we encountered what looked like a message within a message
|
|
* but that is illegal
|
|
*/
|
|
result = HR_BADMSG;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* we're done, restore details for overlying data collection routine */
|
|
hc->rc.hr_ptr_putc = holdptr;
|
|
hc->h_checksum = hold_checksum;
|
|
hc->h_crc = hold_crc;
|
|
*mdata = &hc->rc.rmsg_bufr[3];
|
|
if (result == HR_COMPLETE)
|
|
{
|
|
if (msgn != hc->rc.expected_msg)
|
|
result = HR_LOSTDATA;
|
|
else
|
|
hc->rc.expected_msg = ++hc->rc.expected_msg % 256;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_still_alive
|
|
*
|
|
* DESCRIPTION:
|
|
* This routine is called periodically during receiving. It determines
|
|
* whether it is time to send the sender a 'deadman' message. Since there
|
|
* is no regular response from the receiver to the sender unless errors
|
|
* occur, the deadman message prevents the sender from sending into a void
|
|
* for long periods of time. If the sender doesn't receive ANYTHING from
|
|
* the receiver for the negotiated deadman time, it can assume the receiver
|
|
* is no longer active.
|
|
*
|
|
* ARGUMENTS:
|
|
* force -- TRUE if a deadman notification should be sent whether it is
|
|
* officially time for one or not.
|
|
* timed_out -- TRUE if receiver has timeout and we want sender to know that.
|
|
*
|
|
* RETURNS:
|
|
* nothing
|
|
*/
|
|
void hr_still_alive(struct s_hc *hc, int force, int timed_out)
|
|
{
|
|
char msg[20];
|
|
|
|
if (force || (long)interval(omsg_last(hc)) >= hc->deadmantime)
|
|
{
|
|
omsg_new(hc, 'c');
|
|
if (timed_out)
|
|
omsg_add(hc, "t");
|
|
|
|
/* While we're talking to the sender, we'll let him know how much
|
|
* we've actually received. This lets him clear the table of
|
|
* unacknowledged files that he keeps.
|
|
*/
|
|
// StrFmt(msg, "f%d,%lu", hc->current_filen, hc->rc.checkpoint);
|
|
wsprintf(msg, "f%d,%lu", hc->current_filen, hc->rc.checkpoint);
|
|
omsg_add(hc, msg);
|
|
omsg_send(hc, BURSTSIZE, FALSE, FALSE);
|
|
}
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_kbdint
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
void hr_kbdint(struct s_hc *hc)
|
|
{
|
|
/* TODO: fix this somehow
|
|
if (!hc->ucancel)
|
|
errorline(FALSE, strld(TM_WAIT_CONF));
|
|
*/
|
|
hc->ucancel = TRUE;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_suspend_input
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
void hr_suspend_input(void *hS, int suspend)
|
|
{
|
|
#if FALSE
|
|
if (suspend)
|
|
suspendinput(FLG_DISK_ACTIVE, 5);
|
|
else
|
|
allowinput(FLG_DISK_ACTIVE);
|
|
#endif
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* hr_check_input
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* ARGUEMENTS:
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
void hr_check_input(void *hS, int suspend)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
/********************** end of hpr_rcv0.c ***************************/
|