home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
UUCP_Blars.lzh
/
dcpgpkt.c
< prev
next >
Wrap
Text File
|
1991-09-08
|
18KB
|
851 lines
/*
* dcpgpkt.c
*
* Revised edition of dcp
*
* Stuart Lynne May/87
*
* Copyright (c) Richard H. Lamb 1985, 1986, 1987
* Changes Copyright (c) Stuart Lynne 1987
* Ported to OS-9/68000: Wolfgang Ocker January 1988
*/
/*
* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987
* 3-window "g" ptotocol
* Thanks got to John Gilmore for sending me a copy of Greg Chesson's
* UUCP protocol description-- Obviously invaluable
* Thanks also go to Andrew Tannenbaum for the section on Siding window
* protocols with a program example in his "Computer Networks" book
*/
/*
* included adaptive error counting (weo, 26/05/88)
*/
#include "dcp.h"
#define PKTSIZE 64
#define PKTSIZ2 2
#define HDRSIZE 6
#define MAXTRY 4
#define MAXERR 50 /* Dont want to quit in a middle of a long file*/
#define SUBERR 5 /* minus 5 errors per successfull transmit */
#define TIMEOUT 6 /* could be longer */
#define KPKT 1024/PKTSIZE
#define POK -1
#define SWINDOW 3 /* fixed now, U make it variable */
#define RWINDOW 3
#define NBUF 8 /* always SAME as MAXSEQ ? */
#define MAXSEQ 8
#define between(a,b,c) ((a<=b && b<c) || (c<a && a<=b) || (b<c && c<a))
/*
* packet defines
*/
static int rwl, swl, swu, rwu, nerr, totnerr, nbuffers;
static int npkt, irec, timeout, GOT_SYNC, GOT_HDR;
static int fseq[NBUF], outlen[NBUF], inlen[NBUF], arr[NBUF];
static char outbuf[NBUF][PKTSIZE+1], inbuf[NBUF][PKTSIZE+1];
static unsigned char grpkt[HDRSIZE+1];
static long ftimer[NBUF], acktmr, naktmr, rdtmr;
/*
* g o p e n p k
*
* Sub sub sub packet handler
*/
gopenpk()
{
int i, j, n1, n2, len;
char tmp[PKTSIZE+1];
pktsize = PKTSIZE; /* change it later after the init */
msgtime = MSGTIME; /* not sure I need this for "g" proto */
/*
* initialize proto parameters
*/
swl = totnerr = nerr = nbuffers = npkt = 0;
swl = swu = 1;
rwl = 0;
rwu = RWINDOW - 1;
for (i = 0; i < NBUF; i++) {
ftimer[i] = 0;
arr[i] = FALSE;
}
GOT_SYNC = GOT_HDR = FALSE;
/*
* 3-way handshake
*/
timeout = 2; /* want some timeout capability here */
gspack(7, 0, 0, 0, tmp);
rsrt:
if (nerr >= MAXERR)
return(-1);
/* INIT sequence. Easy fix for variable pktsize and windows.
* I didnt since all the machines I talk to use W=3 PKTSZ=64
* If you do this make sure to reflect the changes in "grpack"
* and "gspack"
*/
switch (grpack(&n1, &n2, &len, tmp)) {
case 7:
gspack(6, 0, 0, 0, tmp);
if ((nerr -= SUBERR) < 0)
nerr = 0;
goto rsrt;
case 6:
if ((nerr -= SUBERR) < 0)
nerr = 0;
gspack(5, 0, 0, 0, tmp);
goto rsrt;
case 5:
if ((nerr -= SUBERR) < 0)
nerr = 0;
break;
default:
nerr++;
totnerr++;
gspack(7, 0, 0, 0, tmp);
goto rsrt;
}
nerr = totnerr = 0;
return(0); /* channel open */
}
/*
* g c l o s e p k
*/
gclosepk()
{
int i;
char tmp[PKTSIZE+1];
timeout = 2;
for (i = 0; i < MAXTRY; i++) {
gspack(CLOSE, 0, 0, 0, tmp);
if (gmachine() == CLOSE)
break;
}
printmsg(0, "number of errors %d (%d) and pkts xfered %d", totnerr, nerr,
npkt);
return(0);
}
/*
* g g e t p k t
*
* Gets no more than a packet's worth of data from
* the "packet i/o state machine". May have to
* periodically run the pkt machine to get some
* packets.
*
* on input: don't care getpkt(data,&len) char *data int len
* on return: data+\0 and length in len. ret(0) if alls well
* ret(-1) if problems (fail).
*/
ggetpkt(cdata, len)
char *cdata;
int *len;
{
int i2, ttmp;
irec = 1;
timeout = 2;
rdtmr = time(&ttmp); /* setup read timeout */
/*
* Wait for the desired packet
*/
while ((arr[rwl]) == FALSE)
if (gmachine() != POK)
return(-1);
rdtmr = 0; /* disable read timeout */
/*
* Got a packet
*/
i2 = rwl; /* <-- mod(,rwindow) for larger than 8 seq no.s */
*len = inlen[i2];
memcpy(cdata, inbuf[i2], *len);
arr[i2] = FALSE;
rwu = (1 + rwu) % MAXSEQ; /* bump rec window */
npkt++;
return(0);
}
/*
* s e n d p k t
*
* Put at most a packet's worth of data in the pkt state
* machine for xmission.
* May have to run the pkt machine a few times to get
* an available output slot.
*
* on input: char *data int len,flg; len=length of data in data.
* flg=2 just send the packet with no wait for ack.
* flg>0 zero out the unused part of the buffer. (for UUCP "msg"
* pkts)
* flg=0 normal data
* return: ret(0) if alls well ret(-1) if problems (fail)
*
*/
gsendpkt(cdata, len, flg)
char *cdata;
int len, flg;
{
register int i, i1;
long ttmp;
irec = 0;
timeout = 0; /* non-blocking reads */
/*
* Wait for input i.e. if weve sent SWINDOW pkts and none have been
* acked, wait for acks
*/
while (nbuffers >= SWINDOW)
if (gmachine() != POK)
return(-1);
i1 = swu; /* <-- If we ever have more than 8 seq no.s, must mod() here */
/*
* Place packet in table and mark unacked
* fill with zeros or not
*/
if (flg) {
strcpy(outbuf[i1], cdata);
len = PKTSIZE;
for (i = strlen(cdata); i < len; i++)
outbuf[i1][i] = '\0';
}
else {
memcpy(outbuf[i1], cdata, len);
outbuf[i1][len] = '\0';
}
/*
* mark packet
*/
outlen[i1] = len;
ftimer[i1] = time(&ttmp);
fseq[i1] = swu;
swu = (1 + swu) % MAXSEQ; /* bump send window */
nbuffers++;
npkt++;
/*
* send it
*/
gspack(DATA, rwl, fseq[i1], outlen[i1], outbuf[i1]);
/*
* send it once then let the pkt machine take it
*/
return(0);
}
/*
* g m a c h i n e
*
* Idealy we would like to fork this process off in an infinite loop
* and send and rec pkts thru "inbuf" and "outbuf". Cant do this in MS-DOS
* so we setup "getpkt" and "sendpkt" to call this routine often and return
* only when the input buffer is empty thus "blocking" the pkt-machine task.
*/
gmachine()
{
register int i1, i2;
int rack, rseq, rlen, dflg;
char rdata[PKTSIZE+1];
long int ttmp, itmp;
reply:
printmsg(6, "*send %d<W<%d, rec %d<W<%d, err %d (%d)", swl, swu, rwl,
rwu, totnerr, nerr);
/*
* waiting for ACKs for swl to swu-1. Next pkt to send=swu
* rwl=expected pkt
*/
printmsg(7, "Kbytes transfered %d errors %d (%d)\r", npkt / KPKT,
totnerr, nerr);
if (nerr >= MAXERR)
goto close;
dflg = 0;
switch (grpack(&rack, &rseq, &rlen, rdata)) {
case CLOSE:
if ((nerr -= SUBERR) < 0)
nerr = 0;
printmsg(5, "**got CLOSE");
goto close;
case NAK:
nerr++;
totnerr++;
acktmr = naktmr = 0; /* stop ack/nak timer */
printmsg(5, "**got NAK %d", rack);
/*
* As mentioned by Dave Arnold, rack contains the last CORRECT
* received package. So we have to resend starting at
* (rack + 1) % MAXSEQ.
*/
rack = (1 + rack) % MAXSEQ; /* IS THIS A BUG (weo)? */
nloop:
if (between(swl, rack, swu)) { /* resend rack->(swu-1) */
i1 = rack;
gspack(DATA, rwl, rack, outlen[i1], outbuf[i1]);
printmsg(5, "***resent %d", rack);
ftimer[i1] = time(&ttmp);
rack = (1 + rack) % MAXSEQ;
goto nloop;
}
if (dflg)
return(POK);
goto reply; /* any other stuff ? */
case EMPTY:
printmsg(5, "**got EMPTY");
itmp = time(&ttmp);
if (acktmr)
if ((itmp - acktmr) >= TIMEOUT) { /* ack timed out*/
gspack(ACK, rwl, 0, 0, rdata);
acktmr = itmp;
}
if (naktmr)
if ((itmp - naktmr) >= TIMEOUT) { /* nak timed out*/
gspack(NAK, rwl, 0, 0, rdata);
naktmr = itmp;
}
if (rdtmr)
if ((itmp - rdtmr) >= TIMEOUT) { /* read timed out*/
nerr++;
totnerr++;
gspack(NAK, rwl, 0, 0, rdata);
rdtmr = itmp;
goto reply;
}
/*
* resend any timed out un-acked pkts
*/
for (i2 = swl; between(swl, i2, swu); i2 = (1 + i2) % MAXSEQ) {
acktmr = naktmr = 0; /* reset ack/nak */
i1 = i2;
printmsg(5, "--->seq,elapst %d %ld", i2, (itmp - ftimer[i1]));
if ((itmp - ftimer[i1]) >= TIMEOUT) {
printmsg(5, "***timeout %d", i2);
/*
* since "g" is "go-back-N", when we time out we
* must send the last N pkts in order. The generalized
* sliding window scheme relaxes this reqirment
*/
nerr++;
totnerr++;
dflg = 1; /* same hack */
rack = i2;
goto nloop;
}
}
return(POK);
case ACK:
if ((nerr -= SUBERR) < 0)
nerr = 0;
printmsg(5, "**got ACK %d", rack);
acktmr = naktmr = 0; /* disable ack/nak's */
aloop:
if (between(swl, rack, swu)) { /* S<-- -->(S+W-1)%8 */
printmsg(5, "***ACK %d", swl);
ftimer[swl] = 0;
nbuffers--;
swl = (1 + swl) % MAXSEQ;
dflg = 1; /* same hack, sl */
goto aloop;
}
if (dflg)
return(POK); /* hack for non-mtask sys's */
/*
* to empty "inbuf[]"
*/
goto reply;
case DATA:
if ((nerr -= SUBERR) < 0)
nerr = 0;
printmsg(5, "**got DATA %d %d", rack, rseq);
i1 = (1 + rwl) % MAXSEQ; /* (R+1)%8 <-- -->(R+W)%8 */
i2 = (1 + rwu) % MAXSEQ;
if (between(i1, rseq, i2)) {
if (i1 == rseq) {
i1 = rseq;
arr[i1] = TRUE;
inlen[i1] = rlen;
memcpy(inbuf[i1], rdata, rlen);
rwl = (rwl + 1) % MAXSEQ;
printmsg(5, "***ACK d %d", rwl);
gspack(ACK, rwl, 0, 0, rdata);
acktmr = time(&ttmp); /* enable ack/nak tmout*/
dflg = 1; /* return to caller when finished */
/*
* in a mtask system, unneccesary
*/
}
else {
nerr++;
totnerr++;
printmsg(5, "***unexpect %d ne %d", rseq, rwl);
}
}
else {
nerr++;
totnerr++;
printmsg(5, "***wrong seq %d", rseq);
}
goto aloop;
case ERROR:
nerr++;
totnerr++;
printmsg(5, "**got BAD CHK");
gspack(NAK, rwl, 0, 0, rdata);
naktmr = time(&ttmp); /* set nak timer */
printmsg(5, "***NAK d %d", rwl);
goto reply;
default:
printmsg(5, "**got SCREW UP");
goto reply; /* ignore it */
}
close:
gspack(CLOSE, 0, 0, 0, rdata);
return(CLOSE);
}
/*
* g s p a c k
*
* Framming, send a packet
* nt2=type nt3=pkrec nt4=pksent len=length<=PKTSIZE cnt1= data * ret(0) always
*/
gspack(nt2, nt3, nt4, len, cnt1)
int nt2, nt3, nt4, len;
char cnt1[];
{
register unsigned int check, i;
unsigned char c2, pkt[HDRSIZE+1], dpkerr[10];
if (len > 64)
len = 64;
if (len == 0)
cnt1[0] = '\0';
/*
* Link testing mods- create artificial errors
*
* printf("**n:normal,e:error,l:lost,p:partial,h:bad header,s:new seq--> ");
*
* gets(dpkerr);
*
* if(dpkerr[0] == 's') { sscanf(&dpkerr[1],"%d",&nt4); }
*/
/*
* End Link testing mods
*/
printmsg(5, "send packet type %d, num=%d, n=%d, len=%d", nt2, nt3, nt4, len);
printmsg(5, "data =\n|%.64s|", cnt1);
c2 = '\0';
pkt[0] = '\020';
pkt[4] = nt2 << 3;
nt2 &= 7;
switch (nt2) {
case 1:
break; /* stop protocol */
case 2:
pkt[4] += nt3;
break; /* reject */
case 3:
break;
case 4:
pkt[4] += nt3;
break; /* ack */
case 5:
pkt[4] += SWINDOW;
break; /* 3 windows */
case 6:
pkt[4] += 1;
break; /* pktsiz = 64 (1) */
case 7:
pkt[4] += SWINDOW;
break; /* 3 windows */
case 0:
pkt[4] += 0x80 + nt3 + (nt4 << 3);
c2 = (PKTSIZE - len) & 0xff;
/*
* havn't set it up for VERY LONG pkts with a few
* bytes yet (-128)
*/
if (c2) { /* short packet handling */
pkt[4] += 0x40; /* if len < PKTSIZE */
for (i = PKTSIZE - 1; i > 0; i--)
cnt1[i] = cnt1[i-1];
cnt1[0] = c2;
}
break;
}
pkt[4] &= 0xff;
if (nt2) {
pkt[1] = 9; /* control packet size = 0 (9) */
check = (0xaaaa - pkt[4]) & 0xffff;
}
else {
pkt[1] = PKTSIZ2; /* data packet size = 64 (2) */
check = checksum(cnt1, PKTSIZE);
i = pkt[4]; /* got to do this on PC for ex-or high bits */
i &= 0xff;
check = (check ^ i) & 0xffff;
check = (0xaaaa - check) & 0xffff;
}
pkt[2] = check & 0xff;
pkt[3] = (check >> 8) & 0xff;
pkt[5] = (pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4]) & 0xff;
/*
* More Link testing MODS
*
*
* switch(dpkerr[0]) {
* case 'e':
* cnt1[10] = -cnt1[10];
* break;
* case 'h':
* pkt[5] = -pkt[5];
* break;
* case 'l':
* return;
* case 'p':
* swrite(pkt, HDRSIZE);
* if(pkt[1] != 9)
* swrite(cnt1, PKTSIZE-3);
* return;
* default:
* break;
* }
*/
/*
* End Link Testing Mods
*/
swrite(pkt, HDRSIZE); /* header is 6-bytes long */
/*
* write(flog, pkt, HDRSIZE);
*/
if (pkt[1] != 9) {
swrite(cnt1, PKTSIZE); /* data is always 64 bytes long */
/*
* write(flog, cnt1, PKTSIZE);
*/
}
}
/*
* g r p a c k
*
* read packet
*
* on return: nt3=pkrec nt4=pksent len=length <=PKTSIZE cnt1=data *
* ret(type) ok; ret(EMPTY) input buf empty; ret(ERROR) bad header;
* ret(EMPTY) lost pkt timeout; ret(ERROR) checksum error;ret(-5) ?
* NOTE :
* sread(buf,n,timeout)
* while(TRUE) {
* if(# of chars available >= n) (without dec internal counter)
* read n chars into buf (decrenent internal char counter)
* break
* else
* if(time>timeout) break
* }
* return(# of chars available)
*/
grpack(nt3, nt4, len, cnt1)
int *nt3, *nt4, *len;
char cnt1[];
{
unsigned int nt1, check, checkchk, i;
unsigned char c, c2;
register int ii;
if (GOT_SYNC)
goto get_hdr;
if (GOT_HDR)
goto get_data;
c = '\0';
while ((c & 0x7f) != '\020')
if (sread(&c, 1, timeout) == 0)
return(EMPTY);
GOT_SYNC = TRUE;
get_hdr:
if (sread(&grpkt[1], HDRSIZE - 1, timeout) < (HDRSIZE - 1))
return(EMPTY);
GOT_SYNC = FALSE;
/*
* i = grpkt[1] ^ grpkt[2] ^ grpkt[3] ^ grpkt[4] ^ grpkt[5];
*/
i = (unsigned) grpkt[1] ^ (unsigned) grpkt[2] ^
(unsigned) grpkt[3] ^ (unsigned) grpkt[4] ^
(unsigned) grpkt[5];
i &= 0xff;
printmsg(10, "prpkt %02x %02x %02x %02x %02x .. %02x ",
grpkt[1], grpkt[2], grpkt[3], grpkt[4], grpkt[5], i);
if (i) { /* bad header */
printmsg(0, "****bad header****");
/*
* I'm not sure whether "g" considers it an empty or error
*/
printmsg(0, "prpkt %02x %02x %02x %02x %02x .. %02x ",
grpkt[1], grpkt[2], grpkt[3], grpkt[4], grpkt[5], i);
return ERROR;
}
GOT_HDR = TRUE;
if ((grpkt[1] &= 0x7f) == 9) { /* control packet */
*len = 0;
c = grpkt[4] & 0xff;
nt1 = c >> 3;
*nt3 = c & 7;
*nt4 = 0;
check = 0;
checkchk = 0;
cnt1[*len] = '\0';
GOT_HDR = FALSE;
}
else { /* data packet */
if (grpkt[1] != PKTSIZ2)
return(-5); /* can't handle other than 64*/
get_data:
if (sread(cnt1, PKTSIZE, timeout) < PKTSIZE)
return(EMPTY);
GOT_HDR = FALSE;
nt1 = 0;
c2 = grpkt[4] & 0xff;
c = c2 & 0x3f;
*nt4 = c >> 3;
*nt3 = c & 7;
i = grpkt[3];
i = (i << 8) & 0xff00;
check = grpkt[2];
check = i | (check & 0xff);
checkchk = checksum(cnt1, PKTSIZE);
i = grpkt[4] | 0x80;
i &= 0xff;
checkchk = 0xaaaa - (checkchk ^ i);
checkchk &= 0xffff;
if (checkchk != check) {
printmsg(4, "***checksum error***");
return(ERROR);
}
*len = PKTSIZE;
/*
* havn't set it up for very long pkts yet (>128) RH Lamb
*/
if (c2 & 0x40) {
ii = (cnt1[0] & 0xff);
*len = (*len - ii) & 0xff;
for (ii = 0; ii < *len; ii++)
cnt1[ii] = cnt1[ii+1];
}
cnt1[*len] = '\0';
}
printmsg(5, "rec packet type %d, num=%d, n=%d, len=%d", nt1, *nt3, *nt4, *len);
printmsg(6, " checksum rec = %x comp = %x, data=\n|%s|", check, checkchk, cnt1);
ii = nt1;
return(ii);
}
/*
* c h e c k s u m
*/
unsigned checksum(data, len)
int len;
char data[];
{
register unsigned int i, j, tmp, chk1, chk2;
chk1 = 0xffff;
chk2 = 0;
j = len;
for (i = 0; i < len; i++) {
if (chk1 & 0x8000) {
chk1 <<= 1;
chk1++;
}
else
chk1 <<= 1;
tmp = chk1;
chk1 += (data[i] & 0xff);
chk2 += chk1 ^ j;
if ((chk1 & 0xffff) <= (tmp & 0xffff))
chk1 ^= chk2;
j--;
}
return(chk1 & 0xffff);
}
/*
* g w r m s g
*
* send a null terminated string out
*/
gwrmsg(typ, buf)
char typ;
char *buf; /* null terminated */
{
}
/*
* g r d m s g
*
* read a null terminated string
*/
grdmsg(buf)
char *buf;
{
}
/*
* g w r d a t a
*
* read a file and send it out
*/
gwrdata(f)
{
}
/*
* g r r d a t a
*
* read in data and send to file
*/
grrdata(f)
{
}
/*
* g r d b l k
*
* read a block of data in
*/
grdblk(blk, len)
{
}
/*
* g w r b l k
*
* write out a block of data
*/
gwrblk(blk, len)
{
}