#include "ufk.h" #include jmp_buf rp_env; /* * s p a c k * * Send a Packet */ spack(type,num,len,data,offset,check) char type, *data, num, check; int len, offset; { int i; /* Temporary variable */ char buffer[7]; /* Packet help buffer */ unsigned int crc, chksum, ck1, ck2, ck3,/* CRC value and checksum */ calc_crc(); register char *p, *bufp; /* Buffer pointer */ char *q; /* Temp pointer */ prtdbgf("Packet transmitted: %d, Type: %c, Length: %d\n",num,type,len); if (!remote && !nooutput) { if (screen) { posit(20,7); printf("%2d",num); } else printf("Xmit: %d\r",num); } if (debug) /* Display outgoing packet */ { if (screen) { clreol(0,12); /* Clear out data area */ clreol(20,11); } if ((debug >= 1) && !remote) { if (screen) { posit(33,7); printf("%c",type); posit(45,7); printf("%4d",len); } else printf("Type: %c Length: %d\n\l",type,len); } if (len != 0) { if ((debug >= 1) && !remote) { if (screen) { posit(20,11); printf("\"%.58s\"",&data[offset]); if (len > 58) { posit(20,12); printf("\"%.58s\"",&data[58+offset]); } } else printf("Data transmitted: \"%.94s\"\n\l",&data[offset]); } prtdbgf("Data transmitted: \"%.94s\"\n",data); } } purgeline(ttyfd); /* Eat old input */ if (sflg || rflg) pack_sent++; /* Count packet */ bufp = buffer; /* Set up buffer pointer */ zero_crc(); /* Initialize CRC calculation */ *bufp++ = mypackstart; /* Packet marker */ if (len > 91) i = 0; /* Use long packet format */ else i = len + check + 2; /* Use normal length */ *bufp++ = tochar(i); /* Send the character count */ chksum = tochar(i); /* Initialize the checksum */ calc_crc(tochar(i)); /* Calculate CRC */ *bufp++ = tochar(num); /* Packet number */ chksum += tochar(num); /* Update checksum */ calc_crc(tochar(num)); /* Calculate CRC */ *bufp++ = type; /* Packet type */ chksum += type; /* Update checksum */ crc = calc_crc(type); /* Calculate CRC */ if (i == 0) { i = len + check; /* account for header and normal checksum */ *bufp = tochar(i / 95); chksum += *bufp; /* Update checksum */ calc_crc(*bufp++); /* Calculate CRC */ *bufp = tochar(i % 95); chksum += *bufp; /* Update checksum */ calc_crc(*bufp++); /* Calculate CRC */ *bufp = tochar((chksum+((chksum & 0300) >> 6)) & 077);/* Hdr checksum */ chksum += *bufp; /* Update checksum */ crc = calc_crc(*bufp++); /* Calculate CRC */ } if ((type == 'N') && (sflg || rflg)) nak_sent++; /* Count nak */ p = data + offset; q = p + len; while (p < q) /* Loop for all data characters */ { chksum += (unsigned char) *p; /* Update checksum */ crc = calc_crc(*p++); /* Calculate CRC */ } chksum &= 0x0fff; /* Prevent overflow */ for (i = 0;i < pad; i++) kwrite(ttyfd,&padchar,1); /* Issue any padding */ kwrite(ttyfd,buffer,bufp-buffer); /* Send start of packet */ if (len != 0) kwrite(ttyfd, &data[offset], len); /* Send the data if any */ bufp = buffer; /* Reset pointer */ switch (check) { case 1: /* One character checksum */ chksum = (((chksum & 0300) >> 6) + chksum) & 077; *bufp++ = (ck1 = tochar(chksum)); /* Put it in the packet */ break; case 2: /* Two character checksum */ *bufp++ = (ck1 = tochar((chksum >> 6) & 077)); *bufp++ = (ck2 = tochar(chksum & 077)); break; case 3: /* Three character CRC */ *bufp++ = (ck1 = tochar((crc >> 12) & 017)); *bufp++ = (ck2 = tochar((crc >> 6) & 077)); *bufp++ = (ck3 = tochar(crc & 077)); } *bufp++ = eol; /* Extra-packet line terminator */ kwrite(ttyfd, buffer,bufp-buffer); /* Send the rest of the packet */ if (sflg || rflg) dchr_sent += len; /* Adjust character counters */ if (debug) { if (debug >= 1) if (screen) posit(60,7); else fputs("Checksum: ",stdout); prtdbgf("Checksum: "); switch(check) { case 1: prtdbg("%02x\n",unchar(ck1)); break; case 2: prtdbg("%02x%02x\n",unchar(ck1),unchar(ck2)); break; case 3: prtdbg("%02x%02x%02x\n",unchar(ck1),unchar(ck2),unchar(ck3)); } if (!screen) fputs("\l",stdout); } if (sflg) disp_size_transferred(); /* Show how far we've got */ } /* * r p a c k * * Read a Packet */ rpack(len,num,data,check) char *num, check, /* number, checksum type */ *data; /* Packet data */ int *len; /* Length */ { int done, s; unsigned int cchksum, /* Checksums */ rchksum, ck1, ck2, ck3, crc; /* and CRC */ char t, /* Current input character */ type, /* Packet type */ type0, /* Type 0 packet type */ *p; do /* Wait for packet header */ { if (kread(ttyfd,&t,1) == TIMEOUT) return ('T'); /* Return timeout */ t &= 0177; /* Handle parity */ } while (t != mypackstart); done = FALSE; /* Got packet start, init loop */ while (!done) /* Loop to get a packet */ { if (setjmp(rp_env)) return('T'); /* Return if timeout */ zero_crc(); /* Start new CRC calculation */ cchksum = 0; if (getpck(&t,&cchksum,&crc)) continue; /* Resynch if start of packet */ if (unchar(t) == 0) type0 = TRUE; /* Type 0 extended header */ else if ((unchar(t) == 1) || (unchar(t) == 2)) return(FALSE); /* Invalid packet length */ else { type0 = FALSE; *len = unchar(t)-check-2; /* Character count */ } if (getpck(&t,&cchksum,&crc)) continue; /* Resynch if start of packet */ *num = unchar(t); /* Packet number */ if (getpck(&t,&cchksum,&crc)) continue; /* Resynch if start of packet */ type = t; /* Packet type */ if ((type == 'N') && (sflg || rflg)) nak_rec++; /* Count received nak */ if (type0) { if (getpck(&t,&cchksum,&crc)) continue; /* Resynch if start of packet */ *len = 95 * unchar(t); /* First part of length */ if (getpck(&t,&cchksum,&crc)) continue; /* Resynch if start of packet */ *len += unchar(t); /* Second part of length */ *len -= check; /* Correction */ s = cchksum; if (getpck(&t,&cchksum,&crc)) continue; /* Resynch if start of packet */ if (t != tochar((s + ((s & 0300) >> 6)) & 077)) return(FALSE); /* Header checksum error */ } p = data; while (p < data + *len) /* The data itself, if any */ { /* Loop for character count */ if (kread(ttyfd,&t,1) == TIMEOUT)/* Get character */ return ('T'); if (!binfil) /* Handle parity */ t &= 0177; if (t == mypackstart) /* Resynch if start of packet */ continue; cchksum += (unsigned char) t; /* Update checksum */ crc = calc_crc(t); /* Calculate CRC */ *p++ = t; /* Put it in the data buffer */ } cchksum &= 0x0fff; /* Prevent overflow */ *p = '\0'; /* Mark the end of the data */ if (kread(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); if (check == 1) rchksum = (ck1 = unchar(t)); /* Convert to numeric */ else if (check == 2) { rchksum = (ck1 = unchar(t)) << 6; if (kread(ttyfd,&t,1) == TIMEOUT)/* Get character */ return ('T'); rchksum += (ck2 = unchar(t)); } else if (check == 3) { rchksum = (ck1 = unchar(t)) << 12; if (kread(ttyfd,&t,1) == TIMEOUT)/* Get character */ return ('T'); rchksum += (ck2 = unchar(t)) << 6; if (kread(ttyfd,&t,1) == TIMEOUT)/* Get character */ return ('T'); rchksum += (ck3 = unchar(t)); } if (kread(ttyfd,&t,1) == TIMEOUT) /* get EOL character and toss it */ return ('T'); t &= 0177; /* Handle parity */ if (t == mypackstart) /* Resynch if start of packet */ continue; done = TRUE; /* Got checksum, done */ } if (sflg || rflg) { dchr_rec += *len; /* Count received data characters */ pack_rec++; /* Count packet */ } if (check == 3) cchksum = crc; /* Set calculated value */ else if (check == 2) cchksum &= 07777; /* Strip result to 12 bits */ if (check == 1) cchksum = (((cchksum & 0300) >> 6) + cchksum) & 077; /* Final checksum */ prtdbgf("Packet received: %d, Type: %c, Length: %d\n",*num,type,*len); if (!remote && !nooutput) { if (screen) { posit(20,6); printf("%2d",*num); } else printf("Rcv: %d\r",*num); } if (debug) /* Display incoming packet */ { if ((debug >= 1) && !remote) { if (screen) { posit(33,6); printf("%c",type); posit(45,6); printf("%4d",*len); posit(60,6); } else printf("Type: %c Length: %d\n\l",type,*len); } prtdbgf("Checksum: "); if (!screen) fputs("Checksum: ",stdout); switch(check) { case 1: prtdbg("%02x\n",ck1); break; case 2: prtdbg("%02x%02x\n",ck1,ck2); break; case 3: prtdbg("%02x%02x%02x\n",ck1,ck2,ck3); } if (!screen) fputs("\l",stdout); if (screen) { clreol(20,9); clreol(0,10); } if (*len != 0) { if ((debug >= 1) && !remote) { if (screen) { posit(20,9); printf("\"%.58s\"",data); if (*len > 58) { posit(20,10); printf("\"%.58s\"",&data[58]); } } else printf("Data received: \"%.94s\"\n\l",data); } prtdbgf("Data received: \"%.94s\"\n",data); } } if (rflg) disp_size_transferred(); /* Show how far we've got */ if (cchksum != rchksum) return(FALSE); /* Checksum error */ else return(type); /* All OK, return packet type */ } getpck(t,cks,crc) char *t; unsigned int *cks,*crc; { if (kread(ttyfd,t,1) == TIMEOUT) /* Get character */ longjmp(rp_env,TRUE); *t &= 0177; /* Handle parity */ *cks &= 0x0fff; /* Prevent overflow */ *cks += *t; /* Update checksum */ *crc = calc_crc(*t); /* Calculate CRC */ if (*t == mypackstart) return(TRUE); /* New start of packet received */ else return(FALSE); }