home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / CKPM5X_S.ZIP / CKCFN2.C < prev    next >
C/C++ Source or Header  |  1990-03-02  |  32KB  |  936 lines

  1. /*  C K C F N 2  --  System-independent Kermit protocol support functions... */
  2.  
  3. /*** NOTE: there are some sprintf's in here which should probably not be. ***/
  4.  
  5. /*  ...Part 2 (continued from ckcfns.c)  */
  6.  
  7. /*
  8.  Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET),
  9.  Columbia University Center for Computing Activities.
  10.  First released January 1985.
  11.  Copyright (C) 1985, 1989, Trustees of Columbia University in the City of New 
  12.  York.  Permission is granted to any individual or institution to use, copy, or
  13.  redistribute this software so long as it is not sold for profit, provided this
  14.  copyright notice is retained. 
  15. */
  16. /*
  17.  Note -- if you change this file, please amend the version number and date at
  18.  the top of ckcfns.c accordingly.
  19. */
  20.  
  21. #include "ckcsym.h"        /* Conditional compilation (for Macintosh) */
  22. #include "ckcdeb.h"
  23. #include "ckcasc.h"
  24. #include "ckcker.h"
  25. #include "ckcxla.h"
  26.  
  27. extern struct pktinfo s_pkt[];        /* array of pktinfo structures */
  28. extern struct pktinfo r_pkt[];        /* array of pktinfo structures */
  29. extern int sseqtbl[], rseqtbl[], sbufuse[], wslots, winlo, sbufnum;
  30.  
  31. extern int spsiz, spmax, rpsiz, timint, npad, ebq, ebqflg,
  32.  rpt, rptq, rptflg, capas, spsizf;
  33. extern int pktnum, prvpkt, sndtyp, bctr, bctu, rsn, rln, maxtry, size;
  34. extern int osize, maxsize, spktl, nfils, stdouf, warn, timef, parity, speed;
  35. extern int turn, turnch,  delay, displa, pktlog, tralog, seslog, xflg, mypadn;
  36. extern int deblog, hcflg, binary, fncnv, local, server, cxseen, czseen;
  37. extern int nakstate, quiet, success;
  38. extern int spackets, rpackets, timeouts, retrans, crunched, wmax;
  39. extern int tcharset, fcharset;
  40. extern struct csinfo fcsinfo[], tcsinfo[];
  41. extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize;
  42. extern char *cmarg, *cmarg2, **cmlist;
  43. extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate, *hlptxt;
  44. extern CHAR filnam[], *recpkt, *data, srvcmd[], encbuf[];
  45. extern CHAR *srvptr, stchr, mystch, *rdatap;
  46. extern CHAR padbuf[];
  47.  
  48. int numerrs = 0;        /* (PWP) total number packet errors so far */
  49.  
  50. char *strcpy();                /* Forward declarations */
  51. unsigned int chk2();            /* of non-int functions */
  52. unsigned int chk3();
  53. CHAR dopar();                /* ... */
  54.  
  55. char plog[20];                /* For packet logging */
  56.  
  57. static CHAR partab[] = {        /* Even parity table for dopar() */
  58.  
  59.     '\000', '\201', '\202', '\003', '\204', '\005', '\006', '\207',
  60.     '\210', '\011', '\012', '\213', '\014', '\215', '\216', '\017',
  61.     '\220', '\021', '\022', '\223', '\024', '\225', '\226', '\027',
  62.     '\030', '\231', '\232', '\033', '\234', '\035', '\036', '\237',
  63.     '\240', '\041', '\042', '\243', '\044', '\245', '\246', '\047',
  64.     '\050', '\251', '\252', '\053', '\254', '\055', '\056', '\257',
  65.     '\060', '\261', '\262', '\063', '\264', '\065', '\066', '\267',
  66.     '\270', '\071', '\072', '\273', '\074', '\275', '\276', '\077',
  67.     '\300', '\101', '\102', '\303', '\104', '\305', '\306', '\107',
  68.     '\110', '\311', '\312', '\113', '\314', '\115', '\116', '\317',
  69.     '\120', '\321', '\322', '\123', '\324', '\125', '\126', '\327',
  70.     '\330', '\131', '\132', '\333', '\134', '\335', '\336', '\137',
  71.     '\140', '\341', '\342', '\143', '\344', '\145', '\146', '\347',
  72.     '\350', '\151', '\152', '\353', '\154', '\355', '\356', '\157',
  73.     '\360', '\161', '\162', '\363', '\164', '\365', '\366', '\167',
  74.     '\170', '\371', '\372', '\173', '\374', '\175', '\176', '\377'
  75. };
  76.  
  77. /* CRC generation tables */
  78.  
  79. static unsigned int crcta[16] = {0, 010201, 020402, 030603, 041004,
  80.   051205, 061406, 071607, 0102010, 0112211, 0122412, 0132613, 0143014,
  81.   0153215, 0163416, 0173617};
  82.  
  83. static unsigned int crctb[16] = {0, 010611, 021422, 031233, 043044,
  84.   053655, 062466, 072277, 0106110, 0116701, 0127532, 0137323, 0145154,
  85.   0155745, 0164576, 0174367};
  86.  
  87. /*  I N P U T  --  Attempt to read packet number 'pktnum'.  */
  88.  
  89. /*
  90.  This is the function that feeds input to Kermit's finite state machine.
  91.  
  92.  If a special start state is in effect, that state is returned as if it were
  93.  the type of an incoming packet.  Otherwise:
  94.  
  95.  (fill in...)
  96. */
  97.  
  98. input() {
  99.     int numtry, type;
  100.     int i, x, y, k;
  101.  
  102.     debug(F101,"input sstate","",sstate);
  103.     debug(F101," nakstate","",nakstate);
  104.  
  105.     while (1) {                /* Big loop... */
  106.  
  107.     if (sstate != 0) {        /* If a start state is in effect, */
  108.         type = sstate;        /* return it like a packet type, */
  109.         sstate = 0;            /* and then nullify it. */
  110.         numerrs = 0;        /* (PWP) no errors so far */
  111.         return(type);
  112.     }
  113.     
  114.     if (nakstate) {            /* This section for file receiver. */
  115.  
  116.         x = rseqtbl[winlo];        /* See if desired packet already in. */
  117.         debug(F101," winlo","",winlo);
  118.         debug(F101," rseqtbl[winlo]","",rseqtbl[winlo]);
  119.         if (x > -1) {        /* Already there? */
  120.         if (r_pkt[x].pk_seq == winlo) {    /* (double check) */
  121.             rsn = winlo;            /* Yes, return its info */
  122.             debug(F101,"input return pre-stashed packet","",rsn);
  123.             dumprbuf();
  124.             rdatap = r_pkt[x].pk_adr;   /* like rpack would do. */
  125.             rln = strlen(rdatap);
  126.             type = r_pkt[x].pk_typ;
  127.             break;
  128.         }
  129.         }
  130.         type = rpack();            /* Try to read a packet. */
  131.         debug(F111,"input",rdatap,type);
  132.         if (type == sndtyp) type = rpack(); /* Handle echoes */
  133.         if (type < -1) return('q'); /* Ctrl-C */
  134.         if (type < 0) {        /* Receive window full */
  135.         /* Another thing to do here would be to delete */
  136.         /* the highest packet and NAK winlo.  But that */
  137.         /* shouldn't be necessary since the other Kermit */
  138.         /* should not have sent a packet outside the window. */
  139.         debug(F101,"rpack receive window full","",0);
  140.         dumprbuf();
  141.         errpkt("Receive window full.");
  142.         strcpy(recpkt,"Receive window full.");
  143.         return(type = 'E');
  144.         }
  145.         dumprbuf();
  146.  
  147.         chkint();            /* Check for console interrupts. */
  148.         if (type == 'E') break;    /* Error packet */
  149.         if (type == 'Q') {        /* Crunched packet. */
  150.         crunched++;
  151.         numerrs++;
  152.         if (nack(winlo) < 0) {    /* Request resend of window-low.. */
  153.             debug(F101,"input sent too many naks","",winlo);
  154.             errpkt("Too many retries.");
  155.             strcpy(recpkt,"Sent too many NAKs.");
  156.             return(type = 'E');
  157.         } else continue;
  158.         }        
  159.         if (type == 'T') {        /* Timeout */
  160.         int z;            /* NAK all unreceived packets. */
  161.         timeouts++;
  162.         z = winlo + wslots;
  163.         if (z > 63) z -= 64;
  164.         debug(F101,"input sending bulk NAKs, winlo","",winlo);
  165.         for (x = winlo; (x != z) && ttchk() == 0; x++) {
  166.             if (rseqtbl[x] < 0) {
  167.             if (nack(x) < 0) {
  168.                 debug(F101,"input sent too many naks","",winlo);
  169.                 errpkt("Too many retries.");
  170.                 strcpy(recpkt,"Sent too many NAKs.");
  171.                 return(type = 'E');
  172.             }
  173.             }
  174.         }
  175.         continue;
  176.         }
  177.         if (rsn == winlo) {
  178.         debug(F101,"input rsn=winlo","",rsn);
  179.         break;
  180.         }
  181.  
  182.         /* Got a packet out of order. */
  183.  
  184.         debug(F101,"input got data packet out of order","",rsn);
  185.         k = rseqtbl[rsn];        /* Get window index of this packet. */
  186.         debug(F101,"input rseqtbl[rsn]","",k);
  187.         if (k < 0) {
  188.         debug(F101,"input can't find index for rcvd pkt","",rsn);
  189.         errpkt("internal error number 21");
  190.         strcpy(recpkt,"S/W Protocol Error.");
  191.         type = 'E';
  192.         break;
  193.         }        
  194.         y = chkwin(rsn,winlo,wslots); /* See what window it's in. */
  195.         debug(F101,"input chkwin","",y);
  196.         if (y == 0) {        /* This window. */
  197.         debug(F101,"input pkt in window","",rsn);
  198.         r_pkt[k].pk_flg++;
  199.         debug(F101," ack'd bit for this pkt","",r_pkt[k].pk_flg);
  200. #ifdef COMMENT
  201. /* Note: no, we don't want to ACK a packet that's in the current window */
  202. /* but is not at winlo.  Should only ACK packets AFTER they have been */
  203. /* processed! */
  204.         if (r_pkt[k].pk_flg) {    /* If it has been ack'd already */
  205.             if (resend(rsn) < 0) { /* resend the ACK. */
  206.             debug(F101,"input, too many re-acks","",rsn);
  207.             type = 'E';
  208.             errpkt(recpkt);
  209.             break;
  210.             }
  211.         } else {        /* Otherwise */
  212.             ackn(rsn);        /* ack it. */
  213.         }
  214.         continue;
  215. #endif        
  216.         } else if (y == 1) {    /* Previous window. */
  217.         ackn(rsn);        /* *** dangerous!? *** */
  218.         freerbuf(rseqtbl[rsn]);    /* Get rid of it */
  219.         continue;        /* (what if this was an S-Packet?) */
  220.         } else {            /* If not in this or previous window */
  221.         freesbuf(rsn);
  222.         if (nack(winlo) < 0) {    /* NAK winlo. */
  223.             errpkt("Too many retries.");
  224.             strcpy(recpkt,"Timed out."); /* Give up if too many. */
  225.             type = 'E';
  226.             break;
  227.         } else continue;
  228.         }
  229. /*!!!*/
  230.     } else {            /* Otherwise file sender... */
  231.  
  232.         type = rpack();        /* Try to read an ack. */
  233.         debug(F111,"input",rdatap,type);
  234.         if (type == sndtyp) type = rpack(); /* Handle echoes */
  235.         if (type == -2) return('q');
  236.         if (type == -1) {
  237.         errpkt("Internal error number 18");
  238.         strcpy(recpkt,"Can't allocate receive buffer");
  239.         type = 'E';
  240.         break;        
  241.         }
  242.         dumprbuf();            /* debugging */
  243.  
  244.         chkint();            /* Check for console interrupts. */
  245.  
  246.         /* got a packet */
  247.  
  248.         if (type == 'E') break;    /* Error packet */
  249.         if (type == 'Q') {        /* Crunched packet */ 
  250.         crunched++;        /* For statistics */
  251.         numerrs++;        /* For packet resizing */
  252.         x = resend(winlo);    /* Resend window-low */
  253.         if (x < 0) {
  254.             type = 'E';
  255.             errpkt(recpkt);
  256.             break;
  257.         } else continue;        
  258.         }
  259.         if (type == 'T') {        /* Timeout waiting for ACKs. */
  260.         int z;            /* Resend all un-ACK'd packets. */
  261.         timeouts++;
  262.         z = (pktnum+1)%64;
  263.         debug(F101,"input resending unack'd packets, winlo","",winlo);
  264.         debug(F101," pktnum","",pktnum);
  265.         for (x = winlo; (x != z) && (ttchk() == 0); (x = (x+1)%64)) {
  266.             if (x < 0 || x > 63) {
  267.             debug(F101,"input resend invalid packet","",x);
  268.             continue;
  269.             }
  270.             if ((k = sseqtbl[x]) > -1) {
  271.             if (k > 31) {
  272.                 debug(F101,"input resend invalid slot","",k);
  273.                 continue;
  274.             }
  275.             if (s_pkt[k].pk_flg == 0) { /* If unack'd, resend */
  276.                 if (resend(x) < 0) {    /* Check retries */
  277.                 debug(F101,"input too many resends","",maxtry);
  278.                 errpkt(recpkt);
  279.                 return(type = 'E');
  280.                 }
  281.             } else {    /* Already ACK'd, don't retransmit */
  282.                 debug(F101,"input resend pkt already ack'd","",x);
  283.             }
  284.             } else {        /* Shouldn't happen */
  285.             debug(F101,"input resend can't find pkt","",x);
  286.             }                  
  287.         }
  288.         continue;
  289.         }
  290.  
  291.         /* Got an actual normal packet */
  292.  
  293.         y = chkwin(rsn,winlo,wslots); /* Is it in the window? */
  294.         debug(F101,"input rsn","",rsn);
  295.         debug(F101,"input winlo","",winlo);
  296.         debug(F101,"input chkwin","",y);
  297.         if (type == 'Y') {        /* Got an ACK */
  298.         if (y == 0) {        /* In current window */
  299.             debug(F101,"input ACK in window, freeing buffers","",rsn);
  300.                 freesbuf(rsn);    /* Free the sent packet's buffer */
  301. /*
  302.   NOTE: The following statement frees the buffer of the ACK we just got.
  303.   But the upper layers still need the data, like if it's the ACK to an I,
  304.   S, F, D, Z, or just about any kind of packet.  So for now, freerbuf()
  305.   deallocates the buffer, but does not erase the data or destroy the pointer
  306.   to it.  There's no other single place where these receive buffers can be
  307.   correctly freed (???) ...
  308. */
  309.             freerbuf(rseqtbl[rsn]); /* Free the ACK's buffer */
  310.             if (rsn == winlo) {    /* Got the one we want */
  311.             winlo = (winlo + 1) % 64; /* Rotate window */
  312.             debug(F101,"input/ACK rotated window","",winlo);
  313.             break;        /* Return the ACK */
  314.             }
  315.         } else {        /* ACK not in window, ignore */
  316.             debug(F101,"input ACK out of window","",rsn);
  317.             freerbuf(rseqtbl[rsn]);
  318.             continue;
  319.         }
  320.         }
  321.         if (type == 'N') {        /* NAK */
  322.         debug(F101,"input NAK","",rsn);
  323.         if (y == 0) {        /* In current window */        
  324.             debug(F100," in window","",0);
  325.             freerbuf(rseqtbl[rsn]);
  326.             k = sseqtbl[rsn];
  327.             if (k > -1 && s_pkt[k].pk_typ == ' ') /* Packet */
  328.               x = resend(winlo); /* alloc'd but not yet built. */
  329.             else
  330.               x = resend(rsn);    /* Resend requested packet. */
  331.             if (x < 0) {
  332.             type = 'E';
  333.             errpkt(recpkt);
  334.             break;
  335.             }
  336.         } else if ((rsn == (pktnum + 1) % 64)) {
  337.             if (wslots > 1) {
  338.             debug( F101,"NAK for next packet, windowing","",rsn);
  339.             x = resend(winlo);
  340.             if (x < 0) {
  341.                 type = 'E';
  342.                 errpkt(recpkt);
  343.                 break;
  344.             }
  345.             freerbuf(rseqtbl[rsn]);
  346.             continue;    /* Just ignore it */
  347.             }
  348.             debug(F101," NAK for next packet, no windowing","",rsn);
  349.             freerbuf(rseqtbl[rsn]);
  350.             x = (rsn - 1) % 64;
  351.             if ((x = sseqtbl[x]) > -1) s_pkt[x].pk_flg++;
  352.             type = 'Y';        /* Treat it as ACK for current pkt */
  353.             break;
  354.         } else {
  355.             debug(F101," NAK out of window","",rsn); /* bad... */
  356.             type = 'E';
  357.             errpkt("NAK out of window");
  358.             strcpy(recpkt,"NAK out of window.");
  359.             break;
  360.         }
  361.         }
  362.     }
  363.     }
  364.     debug(F101,"input returning type","",type);
  365.  
  366.     if (wslots == 1)
  367.       ttflui();            /* Got what we want, clear input buffer. */
  368.     if (spktl && !spsizf && !(pktnum & 007))  /* should we recalc pack len? */
  369.       rcalcpsz();        /* (PWP) recalc every 8 packets */
  370.     return(type);        /* Success, return packet type. */
  371. }
  372.  
  373. /*  D O P A R  --  Add an appropriate parity bit to a character  */
  374.  
  375. /*
  376.   (PWP) this is still used in the Mac terminal emulator, so we have to keep it
  377. */
  378. CHAR
  379. dopar(ch)
  380.     register CHAR ch; {
  381.     register unsigned int a;
  382.     if (!parity) return(ch & 255); else a = ch & 127;
  383.     switch (parity) {
  384.     case 'e':  return(partab[a]);        /* Even */
  385.     case 'm':  return(a | 128);         /* Mark */
  386.     case 'o':  return(partab[a] ^ 128); /* Odd */
  387.     case 's':  return(a);            /* Space */
  388.     default:   return(a);
  389.     }
  390. }
  391.  
  392. /*  S P A C K  --  Construct and send a packet  */
  393.  
  394. /*
  395.   spack() sends a packet of the given type, sequence number n, with len data
  396.   characters pointed to by d, in either a regular or extended- length packet,
  397.   depending on length.  Returns the number of bytes actually sent, or else -1
  398.   upon failure.  Uses global npad, padch, mystch, bctu.  Leaves packet fully
  399.   built and null-terminated for later retransmission by resend().  Updates
  400.   global sndpktl (send-packet length).
  401. */
  402.  
  403. spack(type,n,len,d) char type; int n, len; CHAR *d; {
  404.     register int i;
  405.     int j, k, lp, longpkt, copy;
  406.     register CHAR *cp;
  407.     unsigned crc;
  408.  
  409.     debug(F101,"spack n","",n);
  410.     debug(F111," data",data,data);
  411.     debug(F111," d",d,d);
  412.  
  413.     copy = (d != data);            /* Flag whether data must be copied  */
  414.     longpkt = (len + bctu + 2) > 94;    /* Decide whether it's a long packet */
  415.     data = data - 7 + (longpkt ? 0 : 3); /* Starting position of header */
  416.  
  417.     k = sseqtbl[n];            /* Packet structure info for pkt n */ 
  418.     debug(F101," sseqtbl[n]","",k);
  419.     if (k < 0)
  420.       debug(F101,"spack sending packet out of window","",n);
  421.     else
  422.       s_pkt[k].pk_adr = data;        /* Remember address of data field. */
  423.  
  424.     spktl = 0;
  425.     i = 0;
  426.  
  427. /* Now fill the packet */
  428.  
  429.     data[i++] = mystch;            /* MARK */
  430.     lp = i++;                /* Position of LEN, fill in later */
  431.  
  432.     data[i++] = tochar(n);        /* SEQ field */
  433.     data[i++] = sndtyp = type;        /* TYPE field */
  434.     j = len + bctu;            /* Length of data + block check */
  435.     if (longpkt) {            /* Long packet? */
  436.         data[lp] = tochar(0);        /* Yes, set LEN to zero */
  437.         data[i++] = tochar(j / 95);    /* High part */
  438.         data[i++] = tochar(j % 95);    /* Low part */
  439.         data[i] = '\0';            /* Header checksum */
  440.         data[i++] = tochar(chk1(data+lp));
  441.     } else data[lp] = tochar(j+2);    /* Normal LEN */
  442.  
  443.     if (copy)                /* Data field pre-built? */
  444.       for ( ; len--; i++) data[i] = *d++; /* No, must copy. */
  445.     else                /* Otherwise, */
  446.       i += len;                /* Just skip past data field. */
  447.     data[i] = '\0';            /* Null-terminate for checksum calc. */
  448.  
  449.     switch (bctu) {            /* Block check */
  450.     case 1:                /* 1 = 6-bit chksum */
  451.         data[i++] = tochar(chk1(data+lp));
  452.         break;
  453.     case 2:                /* 2 = 12-bit chksum */
  454.         j = chk2(data+lp);
  455.         data[i++] = (unsigned)tochar((j >> 6) & 077);
  456.         data[i++] = (unsigned)tochar(j & 077);
  457.         break;
  458.         case 3:                /* 3 = 16-bit CRC */
  459.         crc = chk3(data+lp);
  460.         data[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);
  461.         data[i++] = (unsigned)tochar((crc >> 6) & 077);
  462.         data[i++] = (unsigned)tochar(crc & 077);
  463.         break;
  464.     }
  465.     data[i++] = seol;            /* End of line (packet terminator) */
  466.     data[i] = '\0';            /* Terminate string */
  467.  
  468.     if (pktlog) {            /* If logging packets, log this one */
  469.     sprintf(plog,"s-%02d-%02d-",n,(gtimer()%60));
  470.     zsout(ZPFILE,plog);
  471.     if (*data) zsoutl(ZPFILE,data);
  472.     }    
  473.     /* (PWP) add the parity quickly at the end */
  474.     switch (parity) {
  475.     case 'e':            /* Even */
  476.         for (cp = &data[i-1]; cp >= data; cp--)
  477.         *cp = partab[*cp];
  478.         break;
  479.     case 'm':            /* Mark */
  480.         for (cp = &data[i-1]; cp >= data; cp--)
  481.         *cp = *cp | 128;
  482.         break;
  483.     case 'o':            /* Odd */
  484.         for (cp = &data[i-1]; cp >= data; cp--)
  485.         *cp = partab[*cp] ^ 128;
  486.         break;
  487.       case 's':
  488.         for (cp = &data[i-1]; cp >= data; cp--)
  489.         *cp = partab[*cp] & 127;
  490.         break;
  491.     }
  492.  
  493.     if (npad) ttol(padbuf,npad);    /* Send any padding */
  494.     spktl = i;                /* Remember packet length */
  495.     if (ttol(data,spktl) < 0) return(-1); /* Send the packet */
  496.     spackets++;
  497.     if (k > -1) {            /* If packet is in window... */
  498.     s_pkt[k].pk_seq = n;        /* Record sequence number */
  499.     s_pkt[k].pk_typ = type;        /* Record packet type */
  500.     s_pkt[k].pk_len = spktl;    /* and length */
  501.     dumpsbuf();
  502.     }
  503.     flco += spktl;            /* Count the characters */
  504.     tlco += spktl;            /* for statistics... */
  505.  
  506.     screen(SCR_PT,type,(long)n,data);    /* Update screen */
  507.     return(i);                /* Return length */
  508. }
  509.  
  510. /*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */
  511.  
  512. chk1(pkt) register CHAR *pkt; {
  513.     register unsigned int chk;
  514.     chk = chk2(pkt);
  515.     chk = (((chk & 0300) >> 6) + chk) & 077;
  516.     return(chk);
  517. }
  518.  
  519. /*  C H K 2  --  Compute the numeric sum of all the bytes in the packet.  */
  520.  
  521. unsigned int
  522. chk2(pkt) register CHAR *pkt; {
  523.     register long chk; register unsigned int m;
  524.     m = (parity) ? 0177 : 0377;
  525.     for (chk = 0; *pkt != '\0'; pkt++)
  526.       chk += *pkt & m;
  527.     return(chk & 07777);
  528. }
  529.  
  530.  
  531. /*  C H K 3  --  Compute a type-3 Kermit block check.  */
  532. /*
  533.  Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup 
  534.  table.  Assumes the argument string contains no embedded nulls.
  535. */
  536. unsigned int
  537. chk3(pkt) register CHAR *pkt; {
  538.     register LONG c, crc;
  539.     register unsigned int m;
  540.     m = (parity) ? 0177 : 0377;
  541.     for (crc = 0; *pkt != '\0'; pkt++) {
  542.     c = (*pkt & m) ^ crc;
  543.     crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);
  544.     }
  545.     return(crc & 0xFFFF);
  546. }
  547.  
  548. nxtpkt() {                /* Called by file sender */
  549.     int i,j,n;
  550.  
  551.     debug(F101,"nxtpkt pktnum","",pktnum);
  552.     debug(F101,"nxtpkt winlo ","",winlo);
  553.     n = (pktnum + 1) % 64;        /* Increment packet number mod 64 */
  554.     j = getsbuf(n);            /* Get a buffer for packet n */
  555.     if (j < 0) {
  556.     debug(F101,"nxtpkt can't get s-buffer","",0);
  557.     return(-1);
  558.     }
  559.     pktnum = n;          
  560.     debug(F101,"nxtpkt bumped pktnum to","",pktnum);
  561.     return(0);
  562. }
  563.  
  564. /* Functions for sending ACKs and NAKs */
  565.  
  566. ack() {                    /* Acknowledge the current packet. */
  567.     return(ackns(winlo,""));
  568. }
  569.  
  570. ackns(n,s) int n; char *s; {        /* Acknowledge packet n */
  571.     int j,k;
  572.     debug(F111,"ackns",s,n);
  573.  
  574.     k = rseqtbl[n];            /* First find received packet n. */
  575.     debug(F101,"ackns k","",k);
  576.     if (k > -1)                /* If in window */
  577.       s_pkt[k].pk_flg++;        /* mark the ack'd bit. */
  578.     else
  579.       debug(F101,"ackns can't set ack'd bit","",k);
  580.  
  581.     /* Now get a buffer for this ack. */
  582.     /* There already might be a NAK sitting in the same buffer, */
  583.     /* In which case we can write over it. */
  584.     if (sseqtbl[n] < 0)    {
  585.     if ((j = getsbuf(n)) < 0)      
  586.       debug(F101,"ackns can't getsbuf","",n);
  587.     }
  588.     spack('Y',n,strlen(s),s);        /* Now send it. */
  589.     debug(F101,"ackns winlo","",winlo);
  590.     debug(F101,"ackns n","",n);
  591.     if (n == winlo) {            /* If we're acking winlo */
  592.     freerbuf(k);            /* don't need it any more */
  593.     freesbuf(j);            /* and don't need to keep ACK either */
  594.     winlo = (winlo + 1) % 64;
  595.     }
  596.     return(0);
  597. }
  598.  
  599. ackn(n) int n; {            /* Send ACK for packet number n */
  600.     return(ackns(n,""));
  601. }
  602.  
  603. ack1(s) char *s; {            /* Send an ACK with data. */
  604.     debug(F110,"ack1",s,0);
  605.     return(ackns(winlo,s));
  606. }
  607.  
  608. nack(n) int n; {            /* Negative acknowledgment. */
  609.     int j,k;
  610.     debug(F101,"nack","",n);
  611.  
  612.     if ((j = sseqtbl[n]) < 0) {        /* If necessary */
  613.     if ((j = getsbuf(n)) < 0) {    /* get a buffer for this NAK */
  614.         debug(F101,"nack can't getsbuf","",n);
  615.         return(0);
  616.     }
  617.     }
  618.     if (r_pkt[j].pk_rtr++ > maxtry)    /* How many times have we done this? */
  619.       return(-1);            /* Too many... */
  620.  
  621. /* Note, don't free this buffer.  Eventually an ACK will come, and that */
  622. /* will set it free.  If not, well, it's back to ground zero anyway...  */
  623.  
  624.     spack('N',n,0,"");            /* NAK's never have data. */
  625.     return(0);
  626. }
  627.  
  628. /*
  629.  * (PWP) recalculate the optimal packet length in the face of errors.
  630.  * This is a modified version of the algorithm by John Chandler in Kermit/370, 
  631.  * see "Dynamic Packet Size Control", Kermit News, V2 #1, June 1988.
  632.  *
  633.  * My implementation minimizes the total overhead equation, which is
  634.  *
  635.  *  Total chars = file_chars + (header_len * num_packs)
  636.  *                           + (errors * (header_len + packet_len))
  637.  *
  638.  * Differentiate with respect to number of chars, solve for packet_len, get:
  639.  *
  640.  *  packet_len = sqrt (file_chars * header_len / errors)
  641.  */
  642.  
  643. rcalcpsz()
  644. {
  645.     register long x, q;
  646.  
  647.     if (numerrs == 0) return;    /* bounds check just in case */
  648.  
  649.     /* overhead on a data packet is npad+5+bctr, plus 3 if extended packet */
  650.     /* an ACK is 5+bctr */
  651.  
  652.     /* first set x = per packet overhead */
  653. #ifdef COMMENT
  654.     /* (PWP) hook for doing windowing code */
  655.     if (window)
  656.     x = (long) (npad+5+bctr);    /* only the packet, don't count the ack */
  657.     else
  658. #endif /* COMMENT */
  659.     x = (long) (npad+5+3+bctr+5+bctr);
  660.  
  661.     /* then set x = packet length ** 2 */
  662.     x = x * ((long) ffc / (long) numerrs);    /* careful of overflow */
  663.     
  664.     /* calculate the long integer sqrt(x) quickly */
  665.     q = 500;
  666.     q = (q + x/q) >> 1;
  667.     q = (q + x/q) >> 1;
  668.     q = (q + x/q) >> 1;
  669.     q = (q + x/q) >> 1;        /* should converge in about 4 steps */
  670.     if ((q > 94) && (q < 130))    /* break-even point for long packets */
  671.     q = 94;
  672.     if (q > spmax) q = spmax;    /* maximum bounds */
  673.     if (q < 10) q = 10;        /* minimum bounds */
  674.     spsiz = q;            /* set new send packet size */
  675. }
  676.  
  677. /*  R E S E N D  --  Retransmit packet n.  */
  678.  
  679. /* Returns 0 or positive on success. */
  680. /* On failure, returns a negative number, and an error message is placed */
  681. /* in recpkt.  All errors are considered fatal.  */
  682.  
  683. resend(n) int n; {            /* Send the old packet again. */
  684.     int k;
  685.     debug(F101,"resend seq","",n);
  686.     if ((k = chkwin(n,winlo,wslots)) != 0) {
  687.     debug(F101,"resend","",n);
  688.     debug(F101,"resend packet not in window","",k);
  689.     if (nakstate && k == 1) {    /* Take a chance... */
  690.         spack('Y',n,0,"");        /* Send an ACK... */
  691.         retrans++;
  692.         return(0);
  693.     } else {
  694.         debug(F100,"resend can't recover","",0);
  695.         strcpy(recpkt,"resend error number 13.");
  696.         return(-2);
  697.     }
  698.     }
  699.     k = sseqtbl[n];            /* OK, it's in the window. */
  700.     debug(F101,"resend pktinfo index","",k);
  701.     if (k < 0) {
  702.     debug(F101,"resend sseqtbl failure for pkt","",n);
  703.     strcpy(recpkt,"resend error number 12.");
  704.     return(-2);
  705.     }
  706.     if (s_pkt[k].pk_rtr++ > maxtry) {
  707.     strcpy(recpkt,"Too many retries.");
  708.     return(-1);
  709.     }
  710.     debug(F101," retry","",s_pkt[k].pk_rtr);
  711.     dumpsbuf();
  712.     if (s_pkt[k].pk_typ == ' ') {
  713.     if (nakstate) {
  714.         nack(n);
  715.         retrans++;
  716.         return(s_pkt[k].pk_rtr);
  717.     } else {            /* No packet to resend! */
  718.         strcpy(recpkt,"resend error number 19.");
  719.         return(-2);
  720.     }
  721.     }
  722.     debug(F111,"resend",s_pkt[k].pk_adr,s_pkt[k].pk_len);
  723.     if (ttol(s_pkt[k].pk_adr,s_pkt[k].pk_len) < 1) {
  724.     debug(F100,"resend ttol failed","",0);
  725.     strcpy(recpkt,"resend error number 52.");
  726.     return(-2);
  727.     }
  728.     retrans++;
  729.     screen(SCR_PT,'%',(long)pktnum,"(resend)");    /* Say resend occurred */
  730.     if (pktlog) {            /* If logging packets, log this one */
  731.     sprintf(plog,"x-%02d-%02d-",n,(gtimer()%60));
  732.     zsout(ZPFILE,plog);
  733.     if (*s_pkt[k].pk_adr) zsoutl(ZPFILE,s_pkt[k].pk_adr);
  734.     }    
  735.     return(0);                /* Return retries. */
  736. }
  737.  
  738. errpkt(reason) char *reason; {        /* Send an error packet. */
  739.     int x;
  740.     encstr(reason);
  741.     spack('E',pktnum,size,encbuf);
  742.     x = quiet; quiet = 1;         /* Close files silently. */
  743.     clsif(); clsof(1);
  744.     quiet = x;
  745.     screen(SCR_TC,0,0l,"");
  746.     success = 0;
  747. }
  748.  
  749. scmd(t,dat) char t, *dat; {        /* Send a packet of the given type */
  750.     encstr(dat);            /* Encode the command string */
  751.     spack(t,pktnum,size,encbuf);
  752. }
  753.  
  754. srinit() {                /* Send R (GET) packet */
  755.     encstr(cmarg);            /* Encode the filename. */
  756.     spack('R',pktnum,size,encbuf);    /* Send the packet. */
  757. }
  758.  
  759. sigint(sig,code) int sig, code; {    /* Terminal interrupt handler */
  760.     if (local) errpkt("User typed ^C");
  761.     debug(F101,"sigint() caught signal","",sig);
  762.     debug(F101," code","",code);
  763.     doexit(GOOD_EXIT);            /* Exit program */
  764. }
  765.  
  766. /* R P A C K  --  Read a Packet */
  767.  
  768. /*
  769.  rpack reads a packet and returns the packet type, or else Q if the
  770.  packet was invalid, or T if a timeout occurred.  Upon successful return, sets
  771.  the values of global rsn (received sequence number),  rln (received
  772.  data length), and rdatap (pointer to null-terminated data field).
  773. */
  774. rpack() {
  775.     register int i, j, x, try, lp;    /* Local variables */
  776.     int k, type;
  777.     unsigned crc;
  778.     CHAR pbc[4];            /* Packet block check */
  779.     CHAR *sohp;                /* Pointer to SOH */
  780.     CHAR e;                /* Packet end character */
  781.  
  782.     debug(F101,"entering rpack, pktnum","",pktnum);
  783.     k = getrbuf();            /* Get a new packet input buffer. */
  784.     debug(F101,"rpack getrbuf","",k);
  785.     if (k < 0) return(-1);        /* Return like this if none free. */
  786.     recpkt = r_pkt[k].bf_adr;
  787.     *recpkt = '\0';            /* Clear receive buffer. */
  788.     sohp = recpkt;            /* Initialize pointers to it. */
  789.     rdatap = recpkt;
  790.     rsn = rln = -1;            /* In case of failure. */
  791.     e = (turn) ? turnch : eol;        /* Use any handshake char for eol */
  792.  
  793. /* Try to get a "line". */
  794.  
  795. /* MUST CHANGE TTINL() to discard everything up to stchr! */
  796.  
  797.     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e);
  798.     if (j < 0) {
  799.     freerbuf(k);            /* Free this buffer */
  800.     if (j < -1) return(j);        /* Bail out if ^C^C typed. */
  801.     debug(F101,"rpack: ttinl fails","",j);
  802.     if (nakstate)
  803.       screen(SCR_PT,'T',(long)winlo,"");
  804.     else
  805.       screen(SCR_PT,'T',(long)pktnum,"");
  806.     if (pktlog) zsoutl(ZPFILE,"<timeout>");
  807.     return('T');            /* Otherwise, call it a timeout. */
  808.     }
  809.     tlci += j;                /* All OK, Count the characters. */
  810.     flci += j;
  811.  
  812. /* THEN eliminate this loop... */
  813.  
  814.     for (i = 0; (recpkt[i] != stchr) && (i < j); i++)
  815.       sohp++;                /* Find mark */
  816.     if (i++ >= j) {            /* Didn't find it. */
  817.     if (pktlog) zsoutl(ZPFILE,"<timeout>");
  818.     freerbuf(k);
  819.     return('T');
  820.     }    
  821.     rpackets++;
  822.     lp = i;                /* Remember LEN position. */
  823.     if ((j = xunchar(recpkt[i++])) == 0) {
  824.         if ((j = lp+5) > MAXRP) return('Q'); /* Long packet */
  825.     x = recpkt[j];            /* Header checksum. */
  826.     recpkt[j] = '\0';        /* Calculate & compare. */
  827.     if (xunchar(x) != chk1(recpkt+lp)) {
  828.         freerbuf(k);
  829.         if (pktlog) zsoutl(ZPFILE,"<crunched:hdr>");
  830.         return('Q');
  831.     }
  832.     recpkt[j] = x;            /* Checksum ok, put it back. */
  833.     rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctu;
  834.     j = 3;                /* Data offset. */
  835.     } else if (j < 3) {
  836.     debug(F101,"rpack packet length less than 3","",j);
  837.     freerbuf(k);
  838.     if (pktlog) zsoutl(ZPFILE,"<crunched:len>");
  839.     return('Q');
  840.     } else {
  841.     rln = j - bctu - 2;        /* Regular packet */
  842.     j = 0;                /* No extended header */
  843.     }
  844.     rsn = xunchar(recpkt[i++]);        /* Sequence number */
  845.     if (pktlog) {            /* Log what we got */
  846.     sprintf(plog,"r-%02d-%02d-",rsn,(gtimer()%60));
  847.     zsout(ZPFILE,plog);
  848.     if (*sohp) zsoutl(ZPFILE,sohp); else zsoutl(ZPFILE,"");
  849.     }    
  850.     if (rsn < 0 || rsn > 63) {
  851.     debug(F101,"rpack bad sequence number","",rsn);
  852.     freerbuf(k);
  853.     if (pktlog) zsoutl(ZPFILE,"<crunched:seq>");
  854.     return('Q');
  855.     }
  856.     type = recpkt[i++];            /* Packet type */
  857.     i += j;                /* Where data begins */
  858.     rdatap = recpkt+i;            /* The data itself */
  859.     if ((j = rln + i) > r_pkt[k].bf_len ) {
  860.     debug(F101,"packet sticks out too far","",j);
  861.     freerbuf(k);
  862.     if (pktlog) zsoutl(ZPFILE,"<overflow>");
  863.     return('Q');
  864.     }
  865.     for (x = 0; x < bctu; x++)        /* Copy out the block check */
  866.       pbc[x] = recpkt[j+x];
  867.     pbc[x] = '\0';            /* Null-terminate block check string */
  868.     recpkt[j] = '\0';            /*  and the packet data. */
  869.     debug(F101,"rpack bctu","",bctu);
  870.  
  871.     switch (bctu) {            /* Check the block check */
  872.     case 1:
  873.         if (xunchar(*pbc) != chk1(recpkt+lp)) {
  874.         debug(F110,"checked chars",recpkt+lp,0);
  875.             debug(F101,"block check","",xunchar(*pbc));
  876.         debug(F101,"should be","",chk1(recpkt+lp));
  877.         freerbuf(k);
  878.         if (pktlog) zsoutl(ZPFILE,"<crunched:chk1>");
  879.         return('Q');
  880.          }
  881.         break;
  882.     case 2:
  883.         x = xunchar(*pbc) << 6 | xunchar(pbc[1]);
  884.         if (x != chk2(recpkt+lp)) {
  885.         debug(F110,"checked chars",recpkt+lp,0);
  886.             debug(F101,"block check","", x);
  887.         debug(F101,"should be","", chk2(recpkt+lp));
  888.         freerbuf(k);
  889.         if (pktlog) zsoutl(ZPFILE,"<crunched:chk2>");
  890.         return('Q');
  891.         }
  892.         break;
  893.     case 3:
  894.         crc = (xunchar(pbc[0]) << 12)
  895.             | (xunchar(pbc[1]) << 6)
  896.         | (xunchar(pbc[2]));
  897.         if (crc != chk3(recpkt+lp)) {
  898.         debug(F110,"checked chars",recpkt+lp,0);
  899.             debug(F101,"block check","",xunchar(*pbc));
  900.         debug(F101,"should be","",chk3(recpkt+lp));
  901.         freerbuf(k);
  902.         if (pktlog) zsoutl(ZPFILE,"<crunched:chk3>");
  903.         return('Q');
  904.         }
  905.         break;
  906.     default:            /* Shouldn't happen... */
  907.         freerbuf(k);
  908.         if (pktlog) zsoutl(ZPFILE,"<crunched:chkx>");
  909.         return('Q');
  910.     }
  911.     debug(F101,"rpack block check OK","",rsn);
  912.  
  913. /* Now we can believe the sequence number, etc. */
  914. /* Here we violate strict principles of layering, etc, and look at the  */
  915. /* packet sequence number.  If there's already a packet with the same   */
  916. /* number in the window, we remove this one so that the window will not */
  917. /* fill up. */
  918.  
  919.     if ((x = rseqtbl[rsn]) != -1) {    /* Already a packet with this number */
  920.     retrans++;            /* Count it for statistics */
  921.     debug(F101,"rpack got dup","",rsn);
  922.     if (pktlog) zsoutl(ZPFILE,"<duplicate>");
  923.     freerbuf(x);            /* Free old buffer, keep new packet. */
  924.     r_pkt[k].pk_rtr++;        /* Count this as a retransmission. */
  925.     }
  926.  
  927. /* New packet, not seen before, enter it into the "database". */
  928.  
  929.     rseqtbl[rsn] = k;            /* Make back pointer */
  930.     r_pkt[k].pk_seq = rsn;        /* Record in packet info structure */
  931.     r_pkt[k].pk_typ = type;        /* Sequence, type,... */
  932.     r_pkt[k].pk_adr = rdatap;        /* pointer to data buffer */
  933.     screen(SCR_PT,type,(long)rsn,sohp);    /* Update screen */
  934.     return(type);            /* Return packet type */
  935. }
  936.