/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */ /* General sliding window program. Under developement. Has advanteges */ /* over "got-back-N". Was used initially as a vehicle to decypher */ /* the "g: protocol. Modify dcp.h,dcp.c,dcpstart.c and leave out if desired*/ #include "dcp.h" #define PKTSIZE 64 /* framming data */ #define HDRSIZ 5 #define SYNC '\020' #define MAXSEQ 8 /* protocol data */ #define NBUF 4 /*MAXSEQ/2 give explicitly! so type is integer*/ #define MAXERR 20 #define KPKT 1024/PKTSIZE #define TIMEOUT 10 /* should be 4sec */ #define MAXTRY 10 #define between(a,b,c) ((a<=b && b0 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) * */ rsendpkt(data,len,flg) int len,flg; char data[]; { int i,i1; long tmp; if(debug>2) printmsg("\nSendpkt"); machine(); while(nbuffers >= NBUF) machine(); i1 = swu % NBUF; if(flg) {strcpy(outbuf[i1],data); len=PKTSIZE; for(i=strlen(data);i2) printmsg("\nGetpkt"); machine(); while((arr[rwl%NBUF]) == 0) machine(); { if(debug>2) printmsg("ACK %d",rwl); rspack(ACK,rwl,0,0,0); i2 = rwl%NBUF; *len = inlen[i2]; strncpy(data,inbuf[i2],*len); nonak = TRUE; arr[i2] = FALSE; rwl = (1+rwl)%MAXSEQ; rwu = (1+rwu)%MAXSEQ; } return(0); } /************ packet machine *************/ machine() { int rack,rseq,rlen,i1,i2; char rdata[PKTSIZE]; long tmp; reply: if(debug>3) printmsg("Kbytes transfered %d errors %d\r",npkt/KPKT,nerr); if(nerr >= MAXERR) {return(ERROR);} switch(rrpack(&rack,&rseq,&rlen,rdata)) { case CLOSE: if(debug>2) printmsg("got CLOSE"); return(CLOSE); case NAK: if(debug>2) printmsg("got NAK"); if(between(swl,rack,swu)) { i1 = (i2 = rack)%NBUF; rspack(DATA,rwl,i2,outlen[i1],outbuf[i1]);ftimer[i1]=time(&tmp); nerr++; if(debug>2) printmsg("got NAK %d",rack); } goto reply; case EMPTY: if(debug>2) printmsg("got EMPTY"); i1 = time(&tmp); for(i2=0;i2= TIMEOUT) { rspack(DATA,rwl,fseq[i2],outlen[i2],outbuf[i2]); ftimer[i2]=time(&tmp); nerr++; if(debug>2) printmsg("timeout on %d",fseq[i2]); } } } goto ssend; case ACK: if(debug>2) printmsg("got ACK"); while(between(swl,rack,swu)) { if(debug>2) printmsg("got ACK %d",rack); nbuffers--; ftimer[swl % NBUF] = 0; swl = (1+swl)%MAXSEQ; } goto reply; case DATA: if(debug>2) printmsg("got DATA"); if(rseq != rwl && nonak) { /* can comment this out without loss in perfom*/ /*rspack(NAK,rwl,0,0,0);nonak=FALSE;*/ nerr++; if(debug>2) printmsg("out of sequence %d",rseq); } if(between(rwl,rseq,rwu) && arr[rseq%NBUF] == FALSE) { if(debug>2) printmsg("data pass %d",rseq); i1 = rseq%NBUF; arr[i1] = TRUE; inlen[i1] = rlen; strncpy(inbuf[i1],rdata,rlen); } goto reply; case ERROR: nerr++; if(debug>2) printmsg("checksum error %d",rseq); if(nonak) {rspack(NAK,rwl,0,0,0);nonak=FALSE;} goto reply; default: goto ssend; } ssend: {} } /* framming */ /******************** * read packet * on return: nt3=pkrec nt4=pksent len=length <=PKTSIZE cnt1=data * ret(type) ok; ret(-1) input buf empty; ret(-2) bad header; * ret(-3) lost pkt timeout; ret(-4) checksum error;ret(-5) ? rpack(nt3,nt4,len,cnt1) int *nt3,*nt4,*len; char cnt1[]; ********************* * 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[]; ************************/ /******************** rspack *****************/ rspack(ttype,ack,seq,len,data) int ttype,ack,seq,len; char *data; { int i; char msg[HDRSIZ]; msg[0] = SYNC; msg[1] = ttype; msg[2] = ((ack<<4)&0xf0)|(seq&0x0f); msg[3] = len; msg[4] = msg[1]^msg[2]^msg[3]; if(ttype == DATA) for(i=0;i2) {printmsg("rspack: "); printmsg("type=%d seq=%d ack=%d len=%d chk=%d",ttype,seq,ack,len,msg[4]); if(ttype==DATA) {data[len]='\0'; printmsg("|%s|",data); } else {printmsg("||"); } } } /*********** rrpack **********************/ static unsigned char sbuf[512]; rrpack(ack,seq,len,data) int *ack,*seq,*len; char *data; { int i1,timeout=0; /* ideally we only want to check the input buffer */ /* if its empty return(EMPTY) else get the rest of the packet */ if(sread(sbuf,1,timeout)<1) return(EMPTY); i1=HDRSIZ-1; if(sread(&sbuf[1],i1,1)=HDRSIZ) goto rp2; if(head>0) goto rp1; sbuf[0] = (!SYNC); while(sbuf[0] != SYNC) {if(sread(&sbuf[0],1,timeout)<1) return(EMPTY);} head = 1; rp1: i1=HDRSIZ; if((head += sread(&sbuf[head],i1-head,timeout))>4)&0x0f; *seq = sbuf[2]&0x0f; *len = sbuf[3]; sbuf[4] = sbuf[4]^sbuf[3]^sbuf[2]^sbuf[1]; if(sbuf[1] == DATA) for(i1=0;i12) {printmsg("rrpack: "); printmsg("type=%d seq=%d ack=%d len=%d chk=%d",sbuf[1],*seq,*ack,*len,sbuf[4]); data[*len]='\0'; printmsg("|%s|",data); } return(sbuf[1]); }