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

/* File: C:\WACKER\xfer\hpr_snd0.c (Created: 25-Jan-1994)
* created from HAWIN source file
* hpr_snd0.c -- Routines to provide HyperProtocol file send function in
* HyperACCESS.
*
* Copyright 1988,89,1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 3 $
* $Date: 1/11/02 1:45p $
*/
#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"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hpr_snd
*
* DESCRIPTION:
* Handles file sending 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).
* hs_nfiles -- The number of files scheduled to be sent. (Other concurrent
* processes may remove files before we get to them so we may
* not actually send this many files.)
* hs_nbytes -- The total size of all files scheduled to be sent. (See note
* in description of hs_nfiles.)
*
* RETURNS:
* TRUE if the transfer successfully completes. FALSE otherwise.
*/
int hpr_snd(HSESSION hSession, int attended, int hs_nfiles, long hs_nbytes)
{
struct s_hc *hc;
HCOM hCom;
int bailout;
long timer;
register int cc;
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 (!hs_setup(hc, hs_nfiles, hs_nbytes))
{
free(hc);
return TSC_NO_MEM;
}
/* force a file break on the next char. fetch */
hc->sc.hs_ptrgetc = hs_reteof;
/* initialize variables etc. */
hc->h_filebytes = 0L;
// hc->blocksize = 2048;
// hc->blocksize = xfer_blocksize(hSession);
hc->blocksize = max(hc->blocksize, H_MINBLOCK);
hc->current_filen = 0;
hc->deadmantime = 600;
hc->total_tries = 0;
hsdsp_retries(hc, hc->total_tries);
hc->total_dsp = 0L;
hc->total_thru = 0L;
hc->ucancel = FALSE;
hc->usecrc = TRUE; /* to start out */
hc->fhdl = NULL;
hc->sc.nfiles = hs_nfiles;
hc->sc.nbytes = hs_nbytes;
hc->sc.bytes_sent = hc->h_filebytes;
hc->sc.rmtcancel = FALSE;
hc->sc.last_response = (long)startinterval();
hc->sc.lastmsgn = -1;
hc->sc.rmt_compress = FALSE; /* until we hear otherwise */
hc->sc.rmtchkt = H_CRC; /* until we hear otherwise */
hc->sc.started = FALSE;
hc->sc.lasterr_filenum = -1;
hc->sc.lasterr_offset = -1L;
hc->sc.sameplace = 0;
/* setup file table */
hc->sc.ft_current = 0;
hc->sc.ft_top = hc->sc.ft_open = 0;
hc->sc.hs_ftbl[0].filen = 0;
hc->sc.hs_ftbl[0].cntrl = 0;
hc->sc.hs_ftbl[0].status = TSC_OK;
hc->sc.hs_ftbl[0].flength = 0L;
hc->sc.hs_ftbl[0].thru_bytes = 0L;
hc->sc.hs_ftbl[0].dsp_bytes = 0L;
hc->sc.hs_ftbl[0].fname[0] = TEXT('\0');
// strblank(hc->sc.hs_ftbl[0].fname);
omsg_init(hc, FALSE, TRUE);
if ((bailout = setjmp(hc->sc.jb_bailout)) == 0)
{
/* do normal transfer */
// RemoteClear(); /* get rid of possible stacked-up starts */
ComRcvBufrClear(hCom);
/* restarts and file aborts will branch here */
if (setjmp(hc->sc.jb_restart) == 0)
{
/* first time through, wait for receiver to begin */
hsdsp_status(hc, HSS_WAITSTART);
timer = (long)startinterval();
#if defined(NOTIMEOUTS)
while (TRUE)
#else
while ((long)interval(timer) < 600L)
#endif
{
/* prevent deadman timeout */
hc->xfertimer = hc->sc.last_response = (long)startinterval();
hs_background(hc); /* will exit with longjump to restart */
if (hc->ucancel)
longjmp(hc->sc.jb_bailout, TSC_USER_CANNED);
xfer_idle(hc->hSession);
}
hsdsp_event(hc, HSE_NORESP);
longjmp(hc->sc.jb_bailout, TSC_NO_RESPONSE);
}
/* Restarts jump here via longjmp */
hsdsp_status(hc, HSS_SENDING);
hsdsp_progress(hc, 0);
for (;;)/* this loop is only exited by a longjmp to hc->sc.jb_bailout */
{ /* or hc->sc.jb_restart */
hs_background(hc);
if (hs_datasend(hc))
{
/* sent out full data block */
cc = omsg_setnum(hc, (omsg_number(hc) + 1) % 256);
hc->h_checksum += (unsigned)cc;
if (hc->usecrc)
h_crc_calc(hc, (BYTE)cc);
HS_XMIT(hc, (BYTE)cc);
HS_XMIT(hc, (BYTE)((hc->usecrc?hc->h_crc:hc->h_checksum)%256));
HS_XMIT(hc, (BYTE)((hc->usecrc?hc->h_crc:hc->h_checksum)/256));
/* update display */
hsdsp_progress(hc, 0);
hc->datacnt = 0;
hc->h_crc = hc->h_checksum = 0;
}
else /* encountered EOF in data */
{
if (hc->h_filebytes > 0) /* EOF probably got counted */
--hc->h_filebytes;
hc->sc.bytes_sent = hc->h_filebytes;
hsdsp_progress(hc, FILE_DONE);
hs_filebreak(hc, hs_nfiles, hs_nbytes);
}
xfer_idle(hc->hSession);
}
}
else /* a longjmp(hc->sc.jb_bailout, reason) was called */
{
if (bailout == TSC_COMPLETE)
{
bailout = TSC_OK;
}
else
{
hc->xfertime = (long)interval(hc->xfertimer);
if (hc->fhdl)
{
hc->sc.hs_ftbl[hc->sc.ft_current].status = (int)bailout;
fio_close(hc->fhdl);
hc->fhdl = NULL;
}
}
hsdsp_status(hc, bailout == TSC_OK ? HSS_COMPLETE : HSS_CANCELLED);
}
/* cleanup and exit */;
/* make sure final vu meter is displayed full */
hc->total_dsp += hc->sc.hs_ftbl[hc->sc.ft_current].flength;
hc->total_thru += hc->h_filebytes;
hc->h_filebytes = hc->sc.bytes_sent = 0L;
hsdsp_progress(hc, TRANSFER_DONE);
hs_logx(hc, TRUE);
hs_wrapup(hc, attended, bailout);
free(hc);
compress_disable();
return((USHORT)bailout);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hs_dorestart
*
* DESCRIPTION:
* Called when an interrupt message from the receiver requests that
* transmission be restarted from a particular location. (The entire
* transfer is started by an initial request from the receiver to restart
* at file 0, offset 0.
* This routine responds to a restart request by interrupting any current
* data being sent and sending a special restart message. It then sets up
* to resume transmission at a new location
*
* ARGUMENTS:
* filenum -- The file number of the file to restart.
* offset -- The offset into the file specified by filenum.
* msgnum -- The message number of the restart request. This number is
* included in the restart message sent back so the receiver
* will know which restart request it corresponds to.
* abort -- True if the restart is the result of a request by the
* receiving program to abort transfer of the current file.
*
* RETURNS:
* nothing (This function always exits via a longjmp to the restart location
* or to the bailout location)
*/
void hs_dorestart(struct s_hc *hc, int filenum, long offset, int msgnum, int abort)
{
char str[20];
register struct s_ftbl FAR *ft;
int cnt;
long fsize;
HS_XMIT_CLEAR(hc); /* clear any pending data waiting for transmission */
omsg_setnum(hc, -1);/* restart numbering */
omsg_new(hc, 'R'); /* start a special 'R'estart message */
#if FALSE
hc->usecrc = (h_chkt == H_CRC || hc->sc.rmtchkt == H_CRC);
#endif
hc->usecrc = ((hc->h_chkt == H_CRC) || (hc->sc.rmtchkt == H_CRC));
wsprintf(str, "R%c;T%d", tochar(msgnum), hc->usecrc ? H_CRC : H_CHECKSUM);
omsg_add(hc, str);
/* if we're backing up to an earlier point, tell receiver what blocksize
* to use and verify the file number and offset
*/
if (!abort && filenum > 0)
{
/* since the transfer is not error-free, retreat to min. blocksize */
hc->blocksize = H_MINBLOCK;
// StrFmt(str, "B%d;f%d;o%lu", hc->blocksize, filenum, offset);
wsprintf(str, "B%d;f%d;o%lu", hc->blocksize, filenum, offset);
omsg_add(hc, str);
}
omsg_send(hc, 1, TRUE, FALSE);
/* find the requested file in the file table */
while(hc->sc.ft_current >= 0)
{
if (hc->sc.hs_ftbl[hc->sc.ft_current].filen == filenum)
break;
--hc->sc.ft_current;
}
/* if we couldn't find the requested file in the file table it's
Trouble with a capital 'T' */
if (hc->sc.ft_current < 0)
{
hsdsp_event(hc, HSE_ILLEGAL);
longjmp(hc->sc.jb_bailout, TSC_BAD_FORMAT);
}
ft = &hc->sc.hs_ftbl[hc->sc.ft_current]; /* set local ptr. into table for speed */
hc->current_filen = filenum;
/* Check that we're not stuck on an unresolvable problem. Twenty-five
* consecutive requests to restart at the same place means the transfer
* isn't ever likely to succeed. Probably caused by something like
* an intermediate device stripping characters out.
*/
if (hc->sc.lasterr_offset == offset && hc->sc.lasterr_filenum == filenum)
{
if (++hc->sc.sameplace >= 25)
{
ft->status = TSC_ERROR_LIMIT;
hsdsp_event(hc, HSE_ERRLIMIT);
longjmp(hc->sc.jb_bailout, TSC_ERROR_LIMIT);
}
}
else
{
hc->sc.lasterr_offset = offset;
hc->sc.lasterr_filenum = filenum;
hc->sc.sameplace = 0;
}
if (abort && ft->status == TSC_OK) /* aborting current file ? */
ft->status = TSC_RMT_CANNED;
if (hc->ucancel || hc->sc.rmtcancel) /* received restart while trying
to cancel */
for (cnt = hc->sc.ft_current; cnt <= hc->sc.ft_top; ++cnt)
{
hc->sc.hs_ftbl[cnt].status =
(int)(hc->ucancel ? TSC_USER_CANNED : TSC_RMT_CANNED);
}
/* if this isn't a simple backup operation, force the next character
* read to return an EOF which will, in turn, force hs_filebreak to
* be called to handle these more difficult situations
*/
if (filenum == 0 || ft->status != TSC_OK)
hc->sc.hs_ptrgetc = hs_reteof;
else
{
/* reopen file if necessary */
hc->h_filebytes = hc->sc.bytes_sent = offset;
hc->total_dsp = ft->dsp_bytes;
hc->total_thru = ft->thru_bytes;
if (hc->sc.ft_current != hc->sc.ft_open)
{
if (hc->fhdl)
fio_close(hc->fhdl);
hc->fhdl = NULL;
hc->sc.ft_open = hc->sc.ft_current;
if (xfer_opensendfile(hc->hSession, &hc->fhdl, ft->fname, &fsize,
NULL, NULL) != 0)
{
ft->status = TSC_CANT_OPEN;
hc->sc.ft_open = -1;
}
hsdsp_newfile(hc, filenum, ft->fname, fsize);
}
if (ft->status == TSC_OK)
{
if (fio_seek(hc->fhdl, offset, FIO_SEEK_SET) == EOF)
ft->status = TSC_DISK_ERROR;
else
{
hc->sc.hs_ptrgetc = hs_getc;
/* restart compression if necessary */
if (bittest(ft->cntrl, FTC_COMPRESSED))
{
compress_start(&hc->sc.hs_ptrgetc,
hc,
&hc->h_filebytes,
FALSE);
hsdsp_compress(hc, ON);
hsdsp_status(hc, HSS_SENDING);
}
else
hsdsp_compress(hc, OFF);
}
}
}
hc->datacnt = 0;
hc->h_checksum = hc->h_crc = 0;
longjmp(hc->sc.jb_restart, 1);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hs_background
*
* DESCRIPTION:
* Called by the main transfer loops to handle asynchronous background tasks.
* Specifically, the serial port is scanned for incoming messages from the
* receiver. This routine also detects when the receiver has been silent too
* long (and thus may be dead).
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
void hs_background(struct s_hc *hc)
{
hs_rcvmsg(hc);
if (xfer_user_interrupt(hc->hSession))
{
hsdsp_event(hc, HSE_USRCANCEL);
if (hc->ucancel) /* this is the second time */
longjmp(hc->sc.jb_bailout, TSC_USER_CANNED);
else
{
hc->ucancel = TRUE;
/* TODO: fix this somehow */
/* errorline(FALSE, strld(TM_WAIT_CONF)); */
hc->sc.hs_ptrgetc = hs_reteof; /* force sending to break */
}
}
if (xfer_carrier_lost(hc->hSession))
longjmp(hc->sc.jb_bailout, TSC_LOST_CARRIER);
#if !defined(NOTIMEOUTS)
if ((long)interval(hc->sc.last_response) > (hc->deadmantime * 2L + 100L))
{
hsdsp_event(hc, HSE_NORESP);
longjmp(hc->sc.jb_bailout, TSC_NO_RESPONSE);
}
#endif
xfer_idle(hc->hSession);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hs_rcvmsg
*
* DESCRIPTION:
* Called by hs_background to collect messages from the receiver piecemeal
* and call hs_decode_rmsg when a complete message is assembled.
*
* ARGUMENTS:
* none
*
* RETURNS:
* nothing
*/
#define IDLE -1
#define AWAITING_TYPE -2
#define AWAITING_LEN -3
void hs_rcvmsg(struct s_hc *hc)
{
HCOM hCom;
TCHAR cc;
unsigned rm_checksum;
BYTE *sp;
hCom = sessQueryComHdl(hc->hSession);
// while ((cc = RemoteGet()) != -1)
while (mComRcvChar(hCom, &cc) != 0)
{
if ((*hc->dptr = (BYTE)cc) == H_MSGCHAR)
{
/* start receiving new message, even if last one hadn't finished */
hc->rmcnt = AWAITING_TYPE + 1;
hc->dptr = hc->msgdata;
}
// TODO: figure the correct way for this - else if (!isprint(*hc->dptr))
else if ((*hc->dptr < 0x20) || (*hc->dptr > 0x7E))
/* ignore other non-printing characters */;
else
{
switch(--hc->rmcnt)
{
case IDLE:
++hc->rmcnt; /* so we'll still be idle next time */
break;
case AWAITING_TYPE:
++hc->dptr; /* keep type char. */
hc->rmcnt = AWAITING_LEN + 1;
break;
case AWAITING_LEN:
if ((hc->rmcnt = unchar(*hc->dptr)) < 3 || hc->rmcnt > 94)
{
hc->rmcnt = IDLE + 1;
hc->dptr = hc->msgdata;
}
else
++hc->dptr;
break;
default:
++hc->dptr; /* just keep the char. */
break;
case 0: /* just received final char. of message */
hc->rmcnt = IDLE + 1; /* start over with next char. */
/* verify the checksum */
--hc->dptr; /* point to first char of checksum */
rm_checksum = 0;
for (sp = hc->msgdata; sp < hc->dptr; ++sp)
rm_checksum += *sp;
/* sp now points to first check char */
hc->dptr = hc->msgdata;
if (*sp == tochar(rm_checksum & 0x3F) &&
*(sp + 1) == tochar((rm_checksum >> 6) & 0x3F))
{
/* received valid message */
hc->sc.last_response = (long)startinterval();
if (unchar(hc->msgdata[2]) != (BYTE)hc->sc.lastmsgn)
{
/* new message */
*sp = '\0';
hc->sc.lastmsgn = unchar(hc->msgdata[2]);
hs_decode_rmsg(hc, hc->msgdata);
}
}
break;
}
}
xfer_idle(hc->hSession);
}
xfer_idle(hc->hSession);
}
/************************* end of hpr_snd0.c ****************************/