home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume3
/
pcmail
/
part03
/
kphys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-03
|
8KB
|
214 lines
/*++
/* NAME
/* kphys 3
/* SUMMARY
/* k protocol packet exchange
/* PACKAGE
/* uucp across the TUEnet
/* SYNOPSIS
/* #include "kp.h"
/*
/* kspack(fd,type,num,size,data)
/* int fd, num, size;
/* char type, data[MAXPACKSIZ];
/*
/* krpack(fd,num,size,data)
/* int fd, *num, *size;
/* char data[MAXPACKSIZ];
/* DESCRIPTION
/* The functions in this file take care of data framing and verification.
/*
/* Kspack() sends a packet of the specified type and number,
/* and with len data bytes.
/*
/* Krpack() tries to receive a packet and returns: the packet type plus
/* size and data, or TIME (no packet) or FAIL (bad checksum).
/*
/* The data format has been derived from kermit implementations:
/*
/* .nf
/* .in +5
/* SOH packet header, ASCII control-P
/* len (size of data, low 6 bits) + 32
/* len (size of data, high 6 bits) + 32
/* num (packet number mod 64) + 32
/* type packet type
/* check one-byte type-1 kermit checksum
/*
/* The header is followed by checksummed data if len >0:
/*
/* .nf
/* .in +5
/* data len data bytes
/* check1 (upper 2 bits of type-3 kermit 16-bit checksum) + 32
/* check2 (middle 6 bits of type-3 kermit 16-bit checksum) + 32
/* check3 (lower 6 bits of type-3 kermit 16-bit checksum) + 32
/*
/* Every packet is followed by an ASCII carriage return, which is
/* ignored upon reception of a packet. It prevents timeout errors
/* when one byte gets lost (the most common case).
/* BUGS
/* It is yet another convention for data framing.
/* AUTHOR(S)
/* Wietse Venema
/* Eindhoven University of Technology
/* Department of Mathematics and Computer Science
/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
/* CREATION DATE
/* Mon Feb 3 13:38:14 MET 1986
/* LAST MODIFICATION
/* Mon Apr 4 23:43:13 MET 1988
/* VERSION/RELEASE
/* 1.5
/*--*/
#include <signal.h>
#include <setjmp.h>
#include "kp.h"
#define READS(fd,ch) {if (read(fd,&ch,1) < 0) clkint(); if ((ch &= 0177) == SOH) goto SYNC;}
jmp_buf env; /* Environment ptr for timeout longjump */
clkint() /* Timer interrupt handler */
{
longjmp(env,TRUE); /* Tell krpack to give up */
}
kspack(fd,type,num,len,data)
int fd;
char type, *data;
int num, len;
{
char chksum, header[6], chk[3]; /* Checksums, header */
DEBUG(7,"xmt: type %c\n",type);
if (len > 0)
DEBUG(7,"xmt: data %d\n",len);
header[0] = SOH; /* Packet marker (SOH) */
header[1] = tosix(len); /* Send the character count */
chksum = header[1]; /* Initialize the checksum */
header[2] = tosix(len>>OUT); /* Send the character count */
chksum += header[2]; /* Update checksum */
header[3] = tochar(num); /* Packet number */
chksum += header[3]; /* Update checksum */
header[4] = type; /* Packet type */
chksum += header[4]; /* Update checksum */
chksum = (((chksum&0300) >> 6)+chksum)&077; /* Compute header checksum */
header[5] = tochar(chksum); /* Put it in the packet */
write(fd,header,6); /* Send the header */
if (len > 0) { /* Make data packet */
write(fd,data,len); /* Send data */
chk3(data,len,chk); /* Compute 16-bit checksum */
write(fd,chk,3); /* Send checksum */
}
write(fd,"\r",1); /* Extra-packet line terminator */
}
krpack(fd,num,len,data)
int fd;
int *num; /* Packet number */
int *len; /* Packet length */
char *data; /* Packet data */
{
int i; /* Data character number, loop exit */
char t, /* Current input character */
type, /* Packet type */
rchk[3], /* Data checksum from host */
cchk[3], /* Data checksum computed here */
cchksum, /* Our (computed) checksum */
rchksum; /* Header checksum from other host */
if (setjmp(env)) {
DEBUG(7,"rcv: timed out\n","");
return TIME; /* Timed out */
}
signal(SIGALRM,clkint); /* Setup the timeout */
alarm(TIMEOUT);
for (;;) /* Wait for packet header */
READS(fd,t);
SYNC: /* Got SOH */
alarm(TIMEOUT);
DEBUG(7,"rcv: found sync\n","");
READS(fd,t); /* Get character */
cchksum = t; /* Start the checksum */
*len = unchar(t); /* Character count, low six bits */
READS(fd,t); /* Get character */
cchksum += t; /* Update checksum */
*len += (unchar(t)<<OUT); /* Character count, high six bits */
READS(fd,t); /* Get character */
cchksum += t; /* Update checksum */
*num = unchar(t); /* Packet number */
READS(fd,t); /* Get character */
cchksum += t; /* Update checksum */
type = t; /* Packet type */
READS(fd,t); /* Get header checksum */
rchksum = unchar(t); /* Convert to numeric */
/* Fold in bits 7,8 to compute */
cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* header checksum */
if (cchksum != rchksum) {
DEBUG(7,"rcv: bad header\n","");
alarm(0); /* Disable the timer interrupt */
return FAIL;
}
DEBUG(7,"rcv: type %c\n",type);
if ((*len > 0) && (data != NULLP))
{
for (i=0; i<*len; i++) /* The data itself, if any */
{ /* Loop for character count */
READS(fd,t); /* Get character */
data[i] = t; /* Keep data */
}
for (i=0; i<3; i++) /* 16-bit CRC checksum */
{
READS(fd,t); /* Get character */
rchk[i] = t; /* Keep data */
}
chk3(data,*len,cchk); /* Compute CRC */
if (strncmp(rchk,cchk,3)) { /* Check with received CRC */
DEBUG(7,"rcv: bad data\n","");
alarm(0); /* Disable the timer interrupt */
return FAIL;
}
DEBUG(7,"rcv: data %d\n",*len);
}
alarm(0); /* Disable the timer interrupt */
return(type); /* All OK, return packet type */
}
/* C H K 3 -- Compute a type-3 Kermit block check. */
/*
Calculate the 16-bit CRC of a string using a byte-oriented
tableless algorithm invented by Andy Lowry (Columbia University). The
magic number 010201 is derived from the CRC-CCITT polynomial x^16+x^12+x^5+1.
*/
static chk3(s,len,chk)
char *s, *chk;
int len;
{
unsigned int c, q;
long crc = 0;
while (len--) {
c = *s++;
q = (crc ^ c) & 017; /* Low-order nibble */
crc = (crc >> 4) ^ (q * 010201);
q = (crc ^ (c >> 4)) & 017; /* High order nibble */
crc = (crc >> 4) ^ (q * 010201);
}
*chk++ = tochar(((unsigned)(crc & 0170000)) >> 12);
*chk++ = tochar((crc & 07700) >> 6);
*chk++ = tochar(crc & 077);
}