www.pudn.com > commutil.zip > PROTOCOL.CPP
// ******************************************************************** //
// //
// PROTOCOL.CPP //
// Copyright (c) 1993, Michael Holmes and Bob Flanders //
// C++ Communication Utilities //
// //
// Chapter 6: Transferring Files //
// Last changed in chapter 6 //
// //
// This file contains a class and functions common to the //
// implementation of communications protocol. This class //
// relies on an instance of the Comm class for access to the //
// communications port. //
// //
// ******************************************************************** //
class Protocol
{
public:
int TimeOut(long *n); // check for timeout
UINT CRC(char *s, int l), // CRC calculation
CheckSum(char *s, int l); // checksum calculation
void Purge(Comm *c, long to); // purge incoming data
};
/* ******************************************************************** *
*
* CheckSum -- calculate an 8-bit checksum for message
*
* ******************************************************************** */
UINT Protocol::CheckSum(char *s, // message data
int l) // ..and length
{
unsigned
char acc = 0; // accumulator
while (l--) // until out of length
acc += *(unsigned char *) s++; // ..accumulate checksum
return(acc); // return the byte checksum
}
/* ******************************************************************** *
*
* CRC() -- calculate CRC for message
*
* ******************************************************************** */
UINT Protocol::CRC(char *s, // message data
int len) // ..and length
{
UINT acc = 0, // crc accumulator
i; // loop control
while (len--) // loop thru entire message
{
acc = acc ^ (*s++ << 8); // xor in new byte from msg
for (i = 0; i++ < 8;) // loop thru each of 8 bits
if (acc & 0x8000) // q. this bit on?
acc = (acc << 1) ^ 0x1021; // a. yes .. shift and xor
else
acc <<= 1; // else .. just shift
}
_asm mov ax, acc // ax = crc value
_asm xchg ah, al // swap high and low bytes
return (_AX); // ..and return the crc
}
/* ******************************************************************** *
*
* TimeOut -- check for an event timeout
*
* ******************************************************************** */
int Protocol::TimeOut(long *n) // time to wait in ticks
{
static unsigned
long far *timer = (unsigned long far *) // BIOS timer tick counter
MK_FP(0x40, 0x6c), // ..down in low memory
last, // last accessed time
work; // work variable
work = *timer; // get current time
if (*n > 0) // q. first time call?
{
*n = -*n; // a. yes .. change sign
last = work; // ..and initialize counters
}
if (work != last) // q. time pass?
{ // a. yes .. see how much
if (work <= last) // q. clock go past midnite?
(*n)++; // a. yes .. count as 1 tick
else
*n += (UINT)(work - last); // else .. count everything
last = work; // start again w/curr time
}
return(*n >= 0L); // return TRUE at timeout time
}
/* ******************************************************************** *
*
* Purge -- Purge the line until a timeout occurs
*
* ******************************************************************** */
void Protocol::Purge(Comm *c, // comm instance to purge
long to) // timeout value in seconds
{
long timeout; // work timeout value
char ch, // character buffer
lsr, msr; // lsr & msr for read request
timeout = SECS(to); // set the timeout value
for(;;) // forever
{
if (TimeOut(&timeout)) // q. timeout occur?
return; // a. yes .. exit now
if (c->Read(&ch, &lsr, &msr) == 0) // q. any characters?
timeout = SECS(to); // a. yes.. restart timeout
}
}