Annotation of coherent/e/bin/cku179/ckcfn2.c, revision 1.1.1.1

1.1       root        1: /*  C K C F N 2  --  System-independent Kermit protocol support functions... */
                      2: 
                      3: /*  ...Part 2 (continued from ckcfns.c)  */
                      4: 
                      5: /*
                      6:  Author: Frank da Cruz ([email protected], [email protected]),
                      7:  Columbia University Center for Computing Activities.
                      8:  First released January 1985.
                      9:  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New 
                     10:  York.  Permission is granted to any individual or institution to use, copy, or
                     11:  redistribute this software so long as it is not sold for profit, provided this
                     12:  copyright notice is retained. 
                     13: */
                     14: /*
                     15:  Note -- if you change this file, please amend the version number and date at
                     16:  the top of ckcfns.c accordingly.
                     17: */
                     18: 
                     19: #include "ckcsym.h"
                     20: #include "ckcdeb.h"
                     21: #include "ckcasc.h"
                     22: #include "ckcker.h"
                     23: #include "ckcxla.h"
                     24: 
                     25: #ifdef DYNAMIC
                     26: extern struct pktinfo *s_pkt;          /* array of pktinfo structures */
                     27: extern struct pktinfo *r_pkt;          /* array of pktinfo structures */
                     28: #else
                     29: extern struct pktinfo s_pkt[];         /* array of pktinfo structures */
                     30: extern struct pktinfo r_pkt[];         /* array of pktinfo structures */
                     31: #endif /* DYNAMIC */
                     32: 
                     33: extern int sseqtbl[], rseqtbl[], sbufuse[], sacktbl[], wslots, winlo, sbufnum;
                     34: 
                     35: extern int ttprty;                     /* from ckutio.c */
                     36: extern int autopar;
                     37: 
                     38: extern int spsiz, spmax, rpsiz, timint, npad, ebq, ebqflg, pkttim, rtimo,
                     39:  rpt, rptq, rptflg, capas, spsizf, en_fin, tsecs, network, flow;
                     40: extern int pktnum, sndtyp, bctr, bctu, rsn, rln, maxtry, size;
                     41: extern int osize, maxsize, spktl, nfils, stdouf, warn, timef, parity;
                     42: extern int turn, turnch,  delay, displa, pktlog, tralog, seslog, xflg, mypadn;
                     43: extern int hcflg, binary, local, server, cxseen, czseen;
                     44: extern int nakstate, quiet, success, xitsta, what;
                     45: extern int spackets, rpackets, timeouts, retrans, crunched, wmax;
                     46: extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize, speed;
                     47: extern char *cmarg, *cmarg2, filnam[], *hlptxt;
                     48: extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate;
                     49: extern CHAR *recpkt, *data, encbuf[];
                     50: extern CHAR *srvptr, stchr, mystch, *rdatap;
                     51: extern CHAR padbuf[];
                     52: #ifdef DYNAMIC
                     53:   extern CHAR *srvcmd;
                     54: #else
                     55:   extern CHAR srvcmd[];
                     56: #endif /* DYNAMIC */
                     57: 
                     58: int numerrs = 0;               /* (PWP) total number packet errors so far */
                     59: 
                     60: static CHAR partab[] = {               /* Even parity table for dopar(). */
                     61:     (CHAR) '\000',                     /* ANSI C casts '\ooo' constants  */
                     62:     (CHAR) '\201',                     /* to signed char, so we have to  */
                     63:     (CHAR) '\202',                     /* cast back to unsigned char...  */
                     64:     (CHAR) '\003',
                     65:     (CHAR) '\204',
                     66:     (CHAR) '\005',
                     67:     (CHAR) '\006',
                     68:     (CHAR) '\207',
                     69:     (CHAR) '\210',
                     70:     (CHAR) '\011',
                     71:     (CHAR) '\012',
                     72:     (CHAR) '\213',
                     73:     (CHAR) '\014',
                     74:     (CHAR) '\215',
                     75:     (CHAR) '\216',
                     76:     (CHAR) '\017',
                     77:     (CHAR) '\220',
                     78:     (CHAR) '\021',
                     79:     (CHAR) '\022',
                     80:     (CHAR) '\223',
                     81:     (CHAR) '\024',
                     82:     (CHAR) '\225',
                     83:     (CHAR) '\226',
                     84:     (CHAR) '\027',
                     85:     (CHAR) '\030',
                     86:     (CHAR) '\231',
                     87:     (CHAR) '\232',
                     88:     (CHAR) '\033',
                     89:     (CHAR) '\234',
                     90:     (CHAR) '\035',
                     91:     (CHAR) '\036',
                     92:     (CHAR) '\237',
                     93:     (CHAR) '\240',
                     94:     (CHAR) '\041',
                     95:     (CHAR) '\042',
                     96:     (CHAR) '\243',
                     97:     (CHAR) '\044',
                     98:     (CHAR) '\245',
                     99:     (CHAR) '\246',
                    100:     (CHAR) '\047',
                    101:     (CHAR) '\050',
                    102:     (CHAR) '\251',
                    103:     (CHAR) '\252',
                    104:     (CHAR) '\053',
                    105:     (CHAR) '\254',
                    106:     (CHAR) '\055',
                    107:     (CHAR) '\056',
                    108:     (CHAR) '\257',
                    109:     (CHAR) '\060',
                    110:     (CHAR) '\261',
                    111:     (CHAR) '\262',
                    112:     (CHAR) '\063',
                    113:     (CHAR) '\264',
                    114:     (CHAR) '\065',
                    115:     (CHAR) '\066',
                    116:     (CHAR) '\267',
                    117:     (CHAR) '\270',
                    118:     (CHAR) '\071',
                    119:     (CHAR) '\072',
                    120:     (CHAR) '\273',
                    121:     (CHAR) '\074',
                    122:     (CHAR) '\275',
                    123:     (CHAR) '\276',
                    124:     (CHAR) '\077',
                    125:     (CHAR) '\300',
                    126:     (CHAR) '\101',
                    127:     (CHAR) '\102',
                    128:     (CHAR) '\303',
                    129:     (CHAR) '\104',
                    130:     (CHAR) '\305',
                    131:     (CHAR) '\306',
                    132:     (CHAR) '\107',
                    133:     (CHAR) '\110',
                    134:     (CHAR) '\311',
                    135:     (CHAR) '\312',
                    136:     (CHAR) '\113',
                    137:     (CHAR) '\314',
                    138:     (CHAR) '\115',
                    139:     (CHAR) '\116',
                    140:     (CHAR) '\317',
                    141:     (CHAR) '\120',
                    142:     (CHAR) '\321',
                    143:     (CHAR) '\322',
                    144:     (CHAR) '\123',
                    145:     (CHAR) '\324',
                    146:     (CHAR) '\125',
                    147:     (CHAR) '\126',
                    148:     (CHAR) '\327',
                    149:     (CHAR) '\330',
                    150:     (CHAR) '\131',
                    151:     (CHAR) '\132',
                    152:     (CHAR) '\333',
                    153:     (CHAR) '\134',
                    154:     (CHAR) '\335',
                    155:     (CHAR) '\336',
                    156:     (CHAR) '\137',
                    157:     (CHAR) '\140',
                    158:     (CHAR) '\341',
                    159:     (CHAR) '\342',
                    160:     (CHAR) '\143',
                    161:     (CHAR) '\344',
                    162:     (CHAR) '\145',
                    163:     (CHAR) '\146',
                    164:     (CHAR) '\347',
                    165:     (CHAR) '\350',
                    166:     (CHAR) '\151',
                    167:     (CHAR) '\152',
                    168:     (CHAR) '\353',
                    169:     (CHAR) '\154',
                    170:     (CHAR) '\355',
                    171:     (CHAR) '\356',
                    172:     (CHAR) '\157',
                    173:     (CHAR) '\360',
                    174:     (CHAR) '\161',
                    175:     (CHAR) '\162',
                    176:     (CHAR) '\363',
                    177:     (CHAR) '\164',
                    178:     (CHAR) '\365',
                    179:     (CHAR) '\366',
                    180:     (CHAR) '\167',
                    181:     (CHAR) '\170',
                    182:     (CHAR) '\371',
                    183:     (CHAR) '\372',
                    184:     (CHAR) '\173',
                    185:     (CHAR) '\374',
                    186:     (CHAR) '\175',
                    187:     (CHAR) '\176',
                    188:     (CHAR) '\377'
                    189: };
                    190: 
                    191: /* CRC generation tables */
                    192: 
                    193: static long crcta[16] = { 0L, 010201L, 020402L, 030603L, 041004L,
                    194:   051205L, 061406L, 071607L, 0102010L, 0112211L, 0122412L, 0132613L, 0143014L,
                    195:   0153215L, 0163416L, 0173617L };
                    196: 
                    197: static long crctb[16] = { 0L, 010611L, 021422L, 031233L, 043044L,
                    198:   053655L, 062466L, 072277L, 0106110L, 0116701L, 0127532L, 0137323L, 0145154L,
                    199:   0155745L, 0164576L, 0174367L };
                    200: 
                    201: 
                    202: /*  I N P U T  --  Attempt to read packet number 'pktnum'.  */
                    203: 
                    204: /*
                    205:  This is the function that feeds input to Kermit's finite state machine,
                    206:  in the form of a character in the range 32-126, normally a packet type
                    207:  (uppercase letter) or pseudo-packet-type (lowercase letter).
                    208: 
                    209:  If a special start state is in effect, that state is returned as if it were
                    210:  the type of an incoming packet.  Otherwise:
                    211: 
                    212:  (fill in...)
                    213: */
                    214: 
                    215: int
                    216: input() {
                    217:     int type;
                    218:     int x = 0, y, k;
                    219: 
                    220:     debug(F101,"input sstate","",sstate);
                    221:     debug(F101," nakstate","",nakstate);
                    222:     debug(F000," sndtyp","",sndtyp);
                    223: 
                    224:     while (1) {                                /* Big loop... */
                    225: 
                    226:        if (sstate != 0) {              /* If a start state is in effect, */
                    227:            type = sstate;              /* return it like a packet type, */
                    228:            sstate = 0;                 /* and then nullify it. */
                    229:            numerrs = 0;                /* (PWP) no errors so far */
                    230:            return(type);
                    231:        }
                    232:        
                    233:        if (nakstate) {                 /* This section for file receiver. */
                    234: 
                    235:            if (wslots > 1) {           /* If we're doing windows, */
                    236:                x = rseqtbl[winlo];     /* see if desired packet already in. */
                    237:                debug(F101," winlo","",winlo);
                    238:                debug(F101," rseqtbl[winlo]","",rseqtbl[winlo]);
                    239:                if (x > -1) {           /* Already there? */
                    240:                    if (r_pkt[x].pk_seq == winlo) { /* (double check) */
                    241:                        rsn = winlo;                /* Yes, return its info */
                    242:                        debug(F101,"input return pre-stashed packet","",rsn);
                    243:                        dumprbuf();
                    244:                        rdatap = r_pkt[x].pk_adr;   /* like rpack would do. */
                    245:                        rln = (int)strlen((char *) rdatap);
                    246:                        type = r_pkt[x].pk_typ;
                    247:                        break;
                    248:                    }
                    249:                }
                    250:            }
                    251:            type = rpack();             /* Try to read a packet. */
                    252:            debug(F111,"input",(char *) rdatap,(int) type);
                    253:            while (type == sndtyp) {    /* Handle echoes */
                    254:                debug(F000,"echo discarded","",type);
                    255:                freerbuf(rseqtbl[rsn]);
                    256:                type = rpack(); 
                    257:            }           
                    258:            if (type < -1) return('q'); /* Ctrl-C */
                    259:            if (type < 0) {             /* Receive window full */
                    260:                /* Another thing to do here would be to delete */
                    261:                /* the highest packet and NAK winlo.  But that */
                    262:                /* shouldn't be necessary since the other Kermit */
                    263:                /* should not have sent a packet outside the window. */
                    264:                debug(F101,"rpack receive window full","",0);
                    265:                dumprbuf();
                    266:                errpkt((CHAR *)"Receive window full.");
                    267:                strcpy((char *)recpkt,"Receive window full.");
                    268:                type = 'E';
                    269:                break;
                    270:            }
                    271:            dumprbuf();
                    272: 
                    273:            if (chkint() < 0) {         /* Check for console interrupts. */
                    274:                errpkt((CHAR *)"User cancelled.");
                    275:                strcpy((char *)recpkt,"User cancelled.");
                    276:                type = 'E';
                    277:                break;
                    278:            }
                    279:            if (type == 'E') {
                    280:                debug(F101,"input got E, nakstate","",nakstate);
                    281:                break;                  /* Error packet */
                    282:            }
                    283:            if (type == 'Q') {          /* Crunched packet. */
                    284:                crunched++;
                    285:                numerrs++;
                    286:                if (nack(winlo) < 0) {  /* Request resend of window-low.. */
                    287:                    debug(F101,"input sent too many naks","",winlo);
                    288:                    errpkt((CHAR *)"Too many retries.");
                    289:                    strcpy((char *)recpkt,"Sent too many NAKs.");
                    290:                    type = 'E';
                    291:                    break;
                    292:                } else continue;
                    293:            }           
                    294:            if (type == 'T') {          /* Timeout */
                    295: #ifdef BULKNAKS
                    296:                int z;
                    297: #endif
                    298:                timeouts++;
                    299:                debug(F101,"input receive-state timeout, winlo","",winlo);
                    300: #ifdef BULKNAKS
                    301:                z = winlo + wslots;     /* NAK all unACK'd packets */
                    302:                if (z > 63) z -= 64;
                    303:                debug(F101,"input sending bulk NAKs, winlo","",winlo);
                    304:                for (x = winlo; (x != z) && ttchk() == 0; x++) {
                    305:                    if (x < 0 || x > 63) break;
                    306:                    if (rseqtbl[x] < 0) {
                    307:                        if (nack(x) < 0) {
                    308:                            debug(F101,"input sent too many naks","",winlo);
                    309:                            errpkt((CHAR *)"Too many retries.");
                    310:                            strcpy(recpkt,"Sent too many NAKs.");
                    311:                            type = 'E';
                    312:                            break;
                    313:                        }
                    314:                    }
                    315:                }
                    316: #else          /* NAK only the packet at window-low */
                    317:                debug(F101,"input sending NAK for winlo","",winlo);
                    318:                if (nack(winlo) < 0) {
                    319:                    debug(F101,"input sent too many naks","",winlo);
                    320:                    errpkt((CHAR *)"Too many retries.");
                    321:                    strcpy((char *)recpkt,"Sent too many NAKs.");
                    322:                    type = 'E';
                    323:                    break;
                    324:                }
                    325: #endif /* BULKNAKS */
                    326:                continue;
                    327:            }
                    328: 
                    329:            /* Got the packet we want, done. */
                    330: 
                    331:            if (rsn == winlo) {
                    332:                debug(F101,"input rsn=winlo","",rsn);
                    333:                break;
                    334:            }
                    335: 
                    336:            /* Got a packet out of order. */
                    337: 
                    338:            debug(F101,"input got data packet out of order","",rsn);
                    339:            k = rseqtbl[rsn];           /* Get window slot of this packet. */
                    340:            debug(F101,"input rseqtbl[rsn]","",k);
                    341:            if (k < 0) {
                    342:                debug(F101,"input can't find index for rcvd pkt","",rsn);
                    343:                errpkt((CHAR *)"internal error number 21");
                    344:                strcpy((char *)recpkt,"S/W Protocol Error.");
                    345:                type = 'E';
                    346:                break;
                    347:            }           
                    348:            y = chkwin(rsn,winlo,wslots); /* See what window it's in. */
                    349:            debug(F101,"input chkwin","",y);
                    350:            if (y == 1) {               /* Previous window. */
                    351:                ackn(rsn);              /* Send empty ACK */
                    352:                freerpkt(rsn);          /* Get rid of received packet */
                    353:                continue;
                    354:            } else {                    /* In this window or out of range */
                    355:                if (y < 0)              /* If out of range entirely, */
                    356:                  freerpkt(rsn);        /* release its buffer */
                    357: /*
                    358:   We have received a packet, but not the one we want.  If we do nothing,
                    359:   we could be in for a lengthy timeout/retry cycle.  It would seem to
                    360:   make sense to send a NAK for the most desired packet (winlo).  But
                    361:   consider this scenario: a packet arrived damaged so we NAK'd it above;
                    362:   then packets winlo+1, winlo+2, ... winlo+n arrive, each one making us
                    363:   send a NAK for winlo, so the other Kermit gets n NAKs for winlo, and
                    364:   either would have to resend it n times, or if n > retry limit, give up
                    365:   because of too many retries.  So we compromise: If a packet arrives
                    366:   that is not the most desired packet (winlo), we NAK winlo, BUT ONLY IF
                    367:   it has not be NAK'd before.
                    368: */
                    369:                if (s_pkt[k].pk_rtr == 0) {     /* Have we been here before? */
                    370:                    if (nack(winlo) < 0) {      /* No, NAK winlo. */
                    371:                        errpkt((CHAR *)"Too many retries."); /* Too many */
                    372:                        strcpy((char *)recpkt,"Timed out."); /* Give up */
                    373:                        type = 'E';
                    374:                        break;
                    375:                    } else continue;
                    376:                } else continue;
                    377:            }
                    378: /*!!!*/
                    379:        } else {                        /* Otherwise file sender... */
                    380: 
                    381:            if (wslots > 1) {           /* Packet at winlo already ACK'd? */
                    382: #ifdef COMMENT
                    383:                x = sseqtbl[winlo];
                    384:                if (x > -1) {
                    385:                    if (s_pkt[x].pk_flg) {        /* If so,  */
                    386:                        freesbuf(winlo);          /* Free its buffer */
                    387: 
                    388: #else
                    389:                    if (sacktbl[winlo]) {         /* If so,  */
                    390:                        sacktbl[winlo] = 0;       /* Turn off the ACK'd flag */
                    391: #endif
                    392:                        winlo = (winlo + 1) % 64; /* Rotate the window */
                    393:                        type = 'Y';               /* And return ACK */
                    394:                        debug(F101,
                    395:                              "input returning pre-stashed ACK","",winlo-1);
                    396:                        break;
                    397:                    }
                    398: #ifdef COMMENT
                    399:                }
                    400: #endif /* COMMENT */
                    401:            }
                    402: 
                    403:            type = rpack();             /* Try to read an ack. */
                    404:            debug(F111,"input",rdatap,type);
                    405:            while (type == sndtyp) {    /* Handle echoes */
                    406:                debug(F000,"echo discarded","",type);
                    407:                freerbuf(rseqtbl[rsn]);
                    408:                type = rpack(); 
                    409:            }           
                    410:            if (type == -2) return('q');
                    411:            if (type == -1) {
                    412:                errpkt((CHAR *)"Internal error number 18");
                    413:                debug(F101," wslots","",wslots);
                    414:                debug(F101," winlo","",winlo);
                    415:                debug(F101," pktnum","",pktnum);
                    416:                dumprbuf();
                    417:                strcpy((char *)recpkt,"Can't allocate receive buffer");
                    418:                type = 'E';
                    419:                break;
                    420:            }
                    421:            dumprbuf();                 /* debugging */
                    422: 
                    423:            if (chkint() < 0) {         /* Check for console interrupts. */
                    424:                errpkt((CHAR *)"User cancelled.");
                    425:                strcpy((char *)recpkt,"User cancelled.");
                    426:                return(type = 'E');
                    427:            }
                    428: 
                    429:            /* got a packet */
                    430: 
                    431:            if (type == 'E') {
                    432:                debug(F101,"input got E, nakstate","",nakstate);
                    433:                break;                  /* Error packet */
                    434:            }
                    435:            if (type == 'Q') {          /* Crunched packet */ 
                    436:                crunched++;             /* For statistics */
                    437:                numerrs++;              /* For packet resizing */
                    438:                x = resend(winlo);      /* Resend window-low */
                    439:                if (x < 0) {
                    440:                    type = 'E';
                    441:                    errpkt(recpkt);
                    442:                    break;
                    443:                }
                    444:                continue;
                    445:            }
                    446:            if (type == 'T') {          /* Timeout waiting for ACKs. */
                    447: #ifdef BULKNAKS
                    448:                int z;                  /* Resend all un-ACK'd packets. */
                    449: #endif
                    450:                timeouts++;
                    451:                numerrs++;
                    452:                debug(F101,"input send-state timeout, winlo","",winlo);
                    453: #ifdef BULKNAKS
                    454: /* Retransmit all un-ACK'd packets. */
                    455:                z = (pktnum+1)%64;
                    456:                debug(F101,"input resending unack'd packets, winlo","",winlo);
                    457:                debug(F101," pktnum","",pktnum);
                    458:                for (x = winlo; (x != z) && (ttchk() == 0); (x = (x+1)%64)) {
                    459:                    if (x < 0 || x > 63) {
                    460:                        debug(F101,"input resend invalid packet","",x);
                    461:                        continue;
                    462:                    }
                    463:                    if ((k = sseqtbl[x]) > -1) {
                    464:                        if (k > 31) {
                    465:                            debug(F101,"input resend invalid slot","",k);
                    466:                            continue;
                    467:                        }
                    468:                        /* If formed and unack'd, resend */
                    469: 
                    470:                        if (
                    471: #ifdef COMMENT
                    472:                            s_pkt[k].pk_flg == 0
                    473: #else
                    474:                            sacktbl[x] == 0
                    475: #endif
                    476:                            && s_pkt[k].pk_typ != SP) {
                    477:                            if (resend(x) < 0) {    /* Check retries */
                    478:                                debug(F101,"input resend max","",maxtry);
                    479:                                errpkt(recpkt);
                    480:                                return(type = 'E');
                    481:                            }
                    482:                        } else {        /* Already ACK'd, don't retransmit */
                    483:                            debug(F101,"input resend pkt already ack'd","",x);
                    484:                        }
                    485:                    } else {            /* Shouldn't happen */
                    486:                        debug(F101,"input resend can't find pkt","",x);
                    487:                    }                         
                    488:                }
                    489: #else
                    490: /* Just retransmit the oldest un-ACK'd packet. */
                    491:                debug(F101,"input resending winlo","",winlo);
                    492:                if (resend(winlo) < 0) { /* Check retries */
                    493:                    debug(F101,"input too many resends","",maxtry);
                    494:                    errpkt(recpkt);
                    495:                    return(type = 'E');
                    496:                }
                    497: #endif /* BULKNAKS */
                    498:                continue;
                    499:            }
                    500: 
                    501:            /* Got an actual normal packet */
                    502: 
                    503:            y = chkwin(rsn,winlo,wslots); /* Is it in the window? */
                    504:            debug(F101,"input rsn","",rsn);
                    505:            debug(F101,"input winlo","",winlo);
                    506:            debug(F101,"input chkwin","",y);
                    507:            if (type == 'Y') {          /* Got an ACK */
                    508:                if (y == 0) {           /* In current window */
                    509:                    x = sseqtbl[rsn];   /* Mark the packet as ACK'd */
                    510:                    if (x > -1) s_pkt[x].pk_flg++;  /* (old way) */
                    511:                    sacktbl[rsn]++;                 /* (new way) */
                    512: /*
                    513:   NOTE: The following statement frees the buffer of the ACK we just got.
                    514:   But the upper layers still need the data, like if it's the ACK to an I,
                    515:   S, F, D, Z, or just about any kind of packet.  So for now, freerbuf()
                    516:   deallocates the buffer, but does not erase the data or destroy the pointer
                    517:   to it.  There's no other single place where these receive buffers can be
                    518:   correctly freed (?) ...
                    519: */
                    520:                    freerpkt(rsn);      /* Free the ACK's buffer */
                    521:                    freesbuf(rsn);      /* *** Free the sent packet's buffer */
                    522:                    if (rsn == winlo) { /* Got the one we want */
                    523:                        sacktbl[winlo] = 0;
                    524:                        winlo = (winlo + 1) % 64;
                    525:                        debug(F101,"input rotated send window","",winlo);
                    526:                        break;          /* Return the ACK */
                    527:                    } else {
                    528:                        debug(F101,"input mark pkt","",rsn);
                    529:                        continue;       /* Otherwise go read another packet */
                    530:                    }
                    531:                } else {                /* ACK not in window, ignore */
                    532:                    debug(F101,"input ACK out of window","",rsn);
                    533:                    freerpkt(rsn);
                    534:                    continue;
                    535:                }
                    536:            }
                    537:            if (type == 'N') {          /* NAK */
                    538:                numerrs++;              /* Count an error */
                    539:                debug(F101,"input NAK","",rsn);
                    540:                if (y == 0) {           /* In current window */         
                    541:                    debug(F100," in window","",0);
                    542:                    freerpkt(rsn);      /* Free buffer where NAK lies. */
                    543:                    k = sseqtbl[rsn];   /* Get pointer to NAK'd packet. */
                    544:                    x = 0;
                    545:                    if (k < 0 || (k > -1 && s_pkt[k].pk_typ == ' ')) {
                    546:                        x = resend(winlo); /* Packet we haven't sent yet. */
                    547:                    } else {
                    548:                        x = resend(rsn); /* Resend requested packet. */
                    549:                    }
                    550:                    if (x < 0) {        /* Resend error is fatal.  */
                    551:                        type = 'E';
                    552:                        errpkt(recpkt);
                    553:                        break;
                    554:                    } else continue;    /* Resend ok, go read another packet */
                    555:                } else if ((rsn == (pktnum + 1) % 64)) { /* NAK for next pkt */
                    556:                    if (wslots > 1) {
                    557:                        debug( F101,"NAK for next packet, windowing","",rsn);
                    558:                        x = resend(winlo); /* Resend window-low */
                    559:                        if (x < 0) {
                    560:                            type = 'E';
                    561:                            errpkt(recpkt);
                    562:                            break;
                    563:                        }
                    564:                        freerpkt(rsn);
                    565:                        continue;       /* Go back and read another pkt */
                    566:                    }
                    567:                    debug(F101," NAK for next packet, no windowing","",rsn);
                    568:                    freerpkt(rsn);
                    569:                    x = (rsn - 1) % 64;
                    570:                    if ((x = sseqtbl[x]) > -1) {
                    571:                        sacktbl[x]++;      /* (new way) */
                    572:                        s_pkt[x].pk_flg++; /* (old way) */
                    573:                    }
                    574:                    type = 'Y';         /* Treat it as ACK for current pkt */
                    575:                    break;
                    576:                } else if (y > 0) {     /* NAK for pkt we can't resend */
                    577:                    debug(F101," NAK out of window","",rsn); /* bad... */
                    578:                    type = 'E';
                    579:                    errpkt((CHAR *)"NAK out of window");
                    580:                    strcpy((char *)recpkt,"NAK out of window.");
                    581:                    break;
                    582:                } else continue;        /* Ignore other NAKs */
                    583:            }                           /* End of file-sender NAK handler */
                    584: 
                    585:             if (rsn == winlo) {                /* Not ACK, NAK, timeout, etc. */
                    586:                debug(F000,"input unexpected type","",type);
                    587:                break;
                    588:            }
                    589:        }                               /* End of file-sender section */
                    590:     }                                  /* End of input() loop */
                    591:     if (wslots == 1) {
                    592:        debug(F100,"input about to flush","",0);
                    593:        ttflui();               /* Got what we want, clear input buffer. */
                    594:     }
                    595: #ifdef COMMENT
                    596: /* Old complicated and slow method */
                    597:     if (spktl && !spsizf && !(pktnum & 007))  /* should we recalc pack len? */
                    598:       rcalcpsz();              /* (PWP) recalc every 8 packets */
                    599: #else
                    600: /* New simple and fast method */
                    601:     if (!nakstate)             /* When sending */
                    602:       rcalcpsz();              /* recalculate size every packet */
                    603: #endif
                    604:     debug(F000,"input returning type","",type);
                    605:     return(type);              /* Success, return packet type. */
                    606: }
                    607: 
                    608: /*  D O P A R  --  Add an appropriate parity bit to a character  */
                    609: 
                    610: /*
                    611:   (PWP) this is still used in the Mac terminal emulator, so we have to keep it
                    612: */
                    613: CHAR
                    614: #ifdef CK_ANSIC
                    615: dopar(register CHAR ch)
                    616: #else
                    617: dopar(ch) register CHAR ch;
                    618: #endif /* CK_ANSIC */
                    619:     {
                    620:     register unsigned int a;
                    621:     if (!parity) return((CHAR) (ch & 255)); else a = ch & 127;
                    622:     switch (parity) {
                    623:        case 'e':  return(partab[a]);                /* Even */
                    624:        case 'm':  return((CHAR) (a | 128));         /* Mark */
                    625:        case 'o':  return((CHAR) (partab[a] ^ 128)); /* Odd */
                    626:        case 's':  return((CHAR) a);                 /* Space */
                    627:        default:   return((CHAR) a);                 /* Something illegal */
                    628:     }
                    629: }
                    630: 
                    631: #ifdef PARSENSE
                    632: /*  P A R C H K  --  Check if Kermit packet has parity  */
                    633: 
                    634: /*
                    635:   Call with s = pointer to packet, start = packet start character, n = length.
                    636:   Returns 0 if packet has no parity, -1 on error, or, if packet has parity:
                    637:     'e' for even, 'o' for odd, 'm' for mark.  Space parity cannot be sensed.
                    638:   So a return value of 0 really means either space or none.
                    639: */
                    640: int
                    641: #ifdef CK_ANSIC
                    642: parchk(CHAR *s, CHAR start, int n)
                    643: #else
                    644: parchk(s,start,n) CHAR *s, start; int n;
                    645: #endif /* CK_ANSIC */
                    646: /* parchk */ {
                    647:     CHAR s0, s1, s2, s3;
                    648: 
                    649:     debug(F101,"parchk n","",n);
                    650:     debug(F101,"parchk start","",start);
                    651: 
                    652:     s0 = s[0] & 0x7f;                  /* Mark field (usually Ctrl-A) */
                    653: 
                    654:     if (s0 != start || n < 5) return(-1); /* Not a valid packet */
                    655: 
                    656: /* Look at packet control fields, which never have 8th bit set */
                    657: /* First check for no parity, most common case. */
                    658: 
                    659:     if (((s[0] | s[1] | s[2] | s[3]) & 0x80) == 0)
                    660:       return(0);                       /* No parity */
                    661: 
                    662: /* Check for mark parity */
                    663: 
                    664:     if (((s[0] & s[1] & s[2] & s[3]) & 0x80) == 0x80)
                    665:       return('m');                     /* Mark parity */
                    666: 
                    667: /* Packet has some kind of parity */
                    668: /* Make 7-bit copies of control fields */
                    669: 
                    670:     s1 = s[1] & 0x7f;                  /* LEN */
                    671:     s2 = s[2] & 0x7f;                  /* SEQ */
                    672:     s3 = s[3] & 0x7f;                  /* TYPE */
                    673: 
                    674: /* Check for even parity */
                    675: 
                    676:     if ((s[0] == partab[s0]) &&
                    677:         (s[1] == partab[s1]) &&
                    678:         (s[2] == partab[s2]) &&
                    679:        (s[3] == partab[s3]))
                    680:       return('e');
                    681: 
                    682: /* Check for odd parity */
                    683: 
                    684:     if ((s[0] != partab[s0]) &&
                    685:         (s[1] != partab[s1]) &&
                    686:         (s[2] != partab[s2]) &&
                    687:        (s[3] != partab[s3]))
                    688:       return('o');
                    689: 
                    690: /* Otherwise it's probably line noise.  Let checksum calculation catch it. */
                    691: 
                    692:     return(-1);
                    693: }
                    694: #endif /* PARSENSE */
                    695: 
                    696: /*
                    697:   Check to make sure timeout intervals are long enough to allow maximum
                    698:   length packets to get through before the timer goes off.
                    699: */  
                    700: VOID
                    701: chktimo() {
                    702:     int cps; long z;
                    703:     speed = ttgspd();                  /* Get latest speed */
                    704:     if (speed > 0L && !network) {
                    705:        cps = speed / 10L;
                    706:        if (cps > 0) {
                    707:            z = (long) cps * (long) timint; /* Chars per timeout interval */
                    708:            if (z < spmax) {
                    709:                rtimo = timint = pkttim = (spmax / cps) + 2;
                    710:                debug(F101,"chktimo spmax","",timint);
                    711:            }
                    712:            if (z < rpsiz && rpsiz > spmax) {
                    713:                rtimo = timint = pkttim = (rpsiz / cps) + 2;
                    714:                debug(F101,"chktimo rpsiz","",timint);
                    715:            }
                    716:        }
                    717:     }
                    718: }
                    719: 
                    720: /*  S P A C K  --  Construct and send a packet  */
                    721: 
                    722: /*
                    723:   spack() sends a packet of the given type, sequence number n, with len data
                    724:   characters pointed to by d, in either a regular or extended- length packet,
                    725:   depending on len.  Returns the number of bytes actually sent, or else -1
                    726:   upon failure.  Uses global npad, padch, mystch, bctu, data.  Leaves packet 
                    727:   fully built and null-terminated for later retransmission by resend().
                    728:   Updates global sndpktl (send-packet length).
                    729: 
                    730:   NOTE: The global pointer "data" is assumed to point into the 7th position
                    731:   of a character array (presumably in packet buffer for the current packet).
                    732:   It was used by getpkt() to build the packet data field.  spack() fills in
                    733:   the header to the left of the data pointer (the data pointer is defined
                    734:   in getsbuf() in ckcfn3.c).  If the address "d" is the same as "data", then
                    735:   the packet's data field has been built "in place" and need not be copied.
                    736: */
                    737: int
                    738: #ifdef CK_ANSIC
                    739: spack(char pkttyp, int n, int len, CHAR *d)
                    740: #else
                    741: spack(pkttyp,n,len,d) char pkttyp; int n, len; CHAR *d;
                    742: #endif /* CK_ANSIC */
                    743: /* spack */ {
                    744:     register int i;
                    745:     int j, k, lp, longpkt, copy;
                    746:     register CHAR *cp, *mydata;
                    747:     unsigned crc;
                    748: 
                    749:     debug(F101,"spack n","",n);
                    750:     debug(F101," data","",data);
                    751:     debug(F101," d","",d);
                    752: 
                    753:     copy = (d != data);                        /* Flag whether data must be copied  */
                    754:     longpkt = (len + bctu + 2) > 94;   /* Decide whether it's a long packet */
                    755:     mydata = data - 7 + (longpkt ? 0 : 3); /* Starting position of header */
                    756:     debug(F101," mydata","",mydata);
                    757: 
                    758:     k = sseqtbl[n];                    /* Packet structure info for pkt n */ 
                    759:     debug(F101," sseqtbl[n]","",k);
                    760:     if (k < 0) {
                    761:        debug(F101,"spack sending packet out of window","",n);
                    762:     } else {                           /* Record packet info */
                    763:        s_pkt[k].pk_adr = mydata;       /* Remember address of packet. */
                    764:        s_pkt[k].pk_seq = n;            /* Record sequence number */
                    765:        s_pkt[k].pk_typ = pkttyp;       /* Record packet type */
                    766:     }
                    767: 
                    768:     spktl = 0;                         /* Initialize length of this packet */
                    769:     i = 0;                             /* and position in packet. */
                    770: 
                    771: /* Now fill the packet */
                    772: 
                    773:     mydata[i++] = mystch;              /* MARK */
                    774:     lp = i++;                          /* Position of LEN, fill in later */
                    775: 
                    776:     mydata[i++] = tochar(n);           /* SEQ field */
                    777:     mydata[i++] = pkttyp;              /* TYPE field */
                    778:     sndtyp = pkttyp;                   /* Keep a copy */
                    779:     j = len + bctu;                    /* Length of data + block check */
                    780:     if (longpkt) {                     /* Long packet? */
                    781:        int x;                          /* Work around SCO Xenix/286 */
                    782:        x = 95;                         /* compiler bug... */
                    783:        x = j / 95;
                    784:         mydata[lp] = tochar(0);                /* Yes, set LEN to zero */
                    785:         mydata[i++] = tochar(x);       /* High part */
                    786:         mydata[i++] = tochar(j % 95);  /* Low part */
                    787:         mydata[i] = '\0';              /* Header checksum */
                    788:         mydata[i++] = tochar(chk1(mydata+lp));
                    789:     } else mydata[lp] = tochar(j+2);   /* Normal LEN */
                    790: 
                    791:     if (copy)                          /* Data field built in place? */
                    792:       for ( ; len--; i++) mydata[i] = *d++; /* No, must copy. */
                    793:     else                               /* Otherwise, */
                    794:       i += len;                                /* Just skip past data field. */
                    795:     mydata[i] = '\0';                  /* Null-terminate for checksum calc. */
                    796: 
                    797:     switch (bctu) {                    /* Block check */
                    798:        case 1:                         /* 1 = 6-bit chksum */
                    799:            mydata[i++] = tochar(chk1(mydata+lp));
                    800:            break;
                    801:        case 2:                         /* 2 = 12-bit chksum */
                    802:            j = chk2(mydata+lp);
                    803:            mydata[i++] = (unsigned)tochar((j >> 6) & 077);
                    804:            mydata[i++] = (unsigned)tochar(j & 077);
                    805:            break;
                    806:         case 3:                                /* 3 = 16-bit CRC */
                    807:            crc = chk3(mydata+lp);
                    808:            mydata[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);
                    809:            mydata[i++] = (unsigned)tochar((crc >> 6) & 077);
                    810:            mydata[i++] = (unsigned)tochar(crc & 077);
                    811:            break;
                    812:     }
                    813:     mydata[i++] = seol;                        /* End of line (packet terminator) */
                    814:     mydata[i] = '\0';                  /* Terminate string */
                    815:     logpkt('s',n,mydata);              /* Log packet */
                    816: 
                    817:     /* (PWP) add the parity quickly at the end */
                    818:     switch (parity) {
                    819:       case 'e':                                /* Even */
                    820:        for (cp = &mydata[i-1]; cp >= mydata; cp--)
                    821:          *cp = partab[*cp];
                    822:        break;
                    823:       case 'm':                                /* Mark */
                    824:        for (cp = &mydata[i-1]; cp >= mydata; cp--)
                    825:          *cp |= 128;
                    826:        break;
                    827:       case 'o':                                /* Odd */
                    828:        for (cp = &mydata[i-1]; cp >= mydata; cp--)
                    829:          *cp = partab[*cp] ^ 128;
                    830:        break;
                    831:       case 's':                                /* Space */
                    832:        for (cp = &mydata[i-1]; cp >= mydata; cp--)
                    833:          *cp &= 127;
                    834:        break;
                    835:     }
                    836:     if (npad) ttol(padbuf,npad);       /* Send any padding */
                    837:     spktl = i;                         /* Remember packet length */
                    838:     s_pkt[k].pk_len = spktl;           /* also in packet info structure */
                    839:     if (ttol(mydata,spktl) < 0) return(-1); /* Send the packet */
                    840:     spackets++;                                /* Count it. */
                    841:     flco += spktl;                     /* Count the characters */
                    842:     tlco += spktl;                     /* for statistics... */
                    843:     dumpsbuf();                                /* Dump send buffers to debug log */
                    844:     screen(SCR_PT,pkttyp,(long)n,(char *)mydata); /* Update screen */
                    845:     return(spktl);                     /* Return length */
                    846: }
                    847: 
                    848: /*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */
                    849: 
                    850: int
                    851: chk1(pkt) register CHAR *pkt; {
                    852:     register unsigned int chk;
                    853:     chk = chk2(pkt);
                    854:     chk = (((chk & 0300) >> 6) + chk) & 077;
                    855:     return((int) chk);
                    856: }
                    857: 
                    858: /*  C H K 2  --  Compute the numeric sum of all the bytes in the packet.  */
                    859: 
                    860: unsigned int
                    861: chk2(pkt) register CHAR *pkt; {
                    862:     register long chk; register unsigned int m;
                    863:     m = (parity) ? 0177 : 0377;
                    864:     for (chk = 0; *pkt != '\0'; pkt++)
                    865:       chk += *pkt & m;
                    866:     return((unsigned int) (chk & 07777));
                    867: }
                    868: 
                    869: 
                    870: /*  C H K 3  --  Compute a type-3 Kermit block check.  */
                    871: /*
                    872:  Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup 
                    873:  table.  Assumes the argument string contains no embedded nulls.
                    874: */
                    875: unsigned int
                    876: chk3(pkt) register CHAR *pkt; {
                    877:     register long c, crc;
                    878:     register unsigned int m;
                    879:     m = (parity) ? 0177 : 0377;
                    880:     for (crc = 0; *pkt != '\0'; pkt++) {
                    881:        c = crc ^ (long)(*pkt & m);
                    882:        crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);
                    883:     }
                    884:     return((unsigned int) (crc & 0xFFFF));
                    885: }
                    886: 
                    887: int
                    888: nxtpkt() {                             /* Called by file sender */
                    889:     int j, n;
                    890: 
                    891:     debug(F101,"nxtpkt pktnum","",pktnum);
                    892:     debug(F101,"nxtpkt winlo ","",winlo);
                    893:     n = (pktnum + 1) % 64;             /* Increment packet number mod 64 */
                    894: #ifdef COMMENT 
                    895: /*
                    896:   Suggested by Alan Grieg.  A packet can be sent out of window in 
                    897:   circumstances involving acks received out of order, ...  Have to think
                    898:   about this...
                    899: */
                    900:     if (chkwin(n,winlo,wslots)) {
                    901:        debug(F101,"nxtpkt n not in window","",n);
                    902:        return(-1);
                    903:     }
                    904: #endif
                    905:     j = getsbuf(n);                    /* Get a buffer for packet n */
                    906:     if (j < 0) {
                    907:        debug(F101,"nxtpkt can't getsbuf","",j);
                    908:        return(-1);
                    909:     }
                    910:     pktnum = n;              
                    911:     debug(F101,"nxtpkt bumped pktnum to","",pktnum);
                    912:     return(0);
                    913: }
                    914: 
                    915: /* Functions for sending ACKs and NAKs */
                    916: 
                    917: /* Note, we should only ACK the packet at window-low (winlo) */
                    918: /* However, if an old packet arrives again (e.g. because the ACK we sent */
                    919: /* earlier was lost), we ACK it again. */
                    920: 
                    921: int
                    922: ack() {                                        /* Acknowledge the current packet. */
                    923:     return(ackns(winlo,(CHAR *)""));
                    924: }
                    925: 
                    926: int
                    927: ackns(n,s) int n; CHAR *s; {           /* Acknowledge packet n */
                    928:     int j, k;
                    929:     debug(F111,"ackns",s,n);
                    930: 
                    931:     k = rseqtbl[n];                    /* First find received packet n. */
                    932:     debug(F101,"ackns k","",k);
                    933: #ifdef COMMENT
                    934: /* No need to set ACK'd bit, because we're gonna free the buffer now */
                    935:     if (k > -1)                                /* If in window */
                    936:       s_pkt[k].pk_flg++;               /* mark the ack'd bit. */
                    937:     else
                    938:       debug(F101,"ackns can't set ack'd bit","",k);
                    939: #endif
                    940:     freesbuf(n);                       /* Free current send-buffer, if any */
                    941:     if ((j = getsbuf(n)) < 0) {
                    942:        /* This can happen if we have to re-ACK an old packet that has */
                    943:         /* already left the window.  It does no harm. */
                    944:        debug(F101,"ackns can't getsbuf","",n);
                    945:     }
                    946:     spack('Y',n,(int)strlen((char *)s),s); /* Now send it. */
                    947:     debug(F101,"ackns winlo","",winlo);
                    948:     debug(F101,"ackns n","",n);
                    949:     if (n == winlo) {                  /* If we're acking winlo */
                    950:        if (k > -1)
                    951:          freerbuf(k);                  /* don't need it any more */
                    952:        if (j > -1)
                    953:          freesbuf(j);                  /* and don't need to keep ACK either */
                    954:        winlo = (winlo + 1) % 64;
                    955:     }
                    956:     return(0);
                    957: }
                    958: 
                    959: int
                    960: ackn(n) int n; {                       /* Send ACK for packet number n */
                    961:     return(ackns(n,(CHAR *)""));
                    962: }
                    963: 
                    964: int
                    965: ack1(s) CHAR *s; {                     /* Send an ACK with data. */
                    966:     debug(F110,"ack1",(char *) s,0);
                    967:     return(ackns(winlo, s));
                    968: }
                    969: 
                    970: /* N A C K  --   Send a Negative ACKnowledgment. */
                    971: /*
                    972:  Call with the packet number, n, to be NAK'd.
                    973:  Returns -1 if that packet has been NAK'd too many times, otherwise 0.
                    974:  Btw, it is not right to return 0 under error conditions.  This is
                    975:  done because the -1 code is used for cancelling the file transfer.
                    976:  More work is needed here.
                    977: */
                    978: int
                    979: nack(n) int n; {
                    980:     int i;
                    981: 
                    982:     if (n < 0 || n > 63) {
                    983:        debug(F101,"nack bad pkt num","",n);
                    984:        return(0);
                    985:     } else debug(F101,"nack","",n);
                    986:     if ((i = sseqtbl[n]) < 0) {                /* If necessary */
                    987:        if (getsbuf(n) < 0) {           /* get a buffer for this NAK */
                    988:            debug(F101,"nack can't getsbuf","",n);
                    989:            return(0);
                    990:        } else i = sseqtbl[n];          /* New slot number */
                    991:     }
                    992:     if (s_pkt[i].pk_rtr++ > maxtry)    /* How many times have we done this? */
                    993:       return(-1);                      /* Too many... */
                    994: 
                    995: /* Note, don't free this buffer.  Eventually an ACK will come, and that */
                    996: /* will set it free.  If not, well, it's back to ground zero anyway...  */
                    997: 
                    998:     spack('N',n,0,(CHAR *) "");                /* NAKs never have data. */
                    999:     return(0);
                   1000: }
                   1001: 
                   1002: /*
                   1003:  * (PWP) recalculate the optimal packet length in the face of errors.
                   1004:  * This is a modified version of the algorithm by John Chandler in Kermit/370, 
                   1005:  * see "Dynamic Packet Size Control", Kermit News, V2 #1, June 1988.
                   1006:  *
                   1007:  * This implementation minimizes the total overhead equation, which is
                   1008:  *
                   1009:  *   Total chars = file_chars + (header_len * num_packs)
                   1010:  *                            + (errors * (header_len + packet_len))
                   1011:  *
                   1012:  * Differentiate with respect to number of chars, solve for packet_len, get:
                   1013:  *
                   1014:  *   packet_len = sqrt (file_chars * header_len / errors)
                   1015:  */
                   1016: 
                   1017: /*
                   1018:  (FDC) New super-simple algorithm.  If there was an error in the most recent
                   1019:  packet exchange, cut the send-packet size in half, down to a minimum of 20.
                   1020:  If there was no error, increase the size by 5/4, up to the maximum negotiated
                   1021:  length.  Seems to be much more responsive than previous algorithm, which took
                   1022:  forever to recover the original packet length, and it also went crazy under
                   1023:  certain conditions.
                   1024: 
                   1025:  Here's another idea for packet length resizing that keeps a history of the
                   1026:  last n packets.  Push a 1 into the left end of an n-bit shift register if the
                   1027:  current packet is good, otherwise push a zero.  The current n-bit value, w, of
                   1028:  this register is a weighted sum of the noise hits for the last n packets, with
                   1029:  the most recent weighing the most.  The current packet length is some function
                   1030:  of w and the negotiated packet length, like:
                   1031: 
                   1032:    (2^n - 1 - w) / (2^n - 1) * (negotiated length)
                   1033: 
                   1034:  If the present resizing method causes problems, think about this one a little
                   1035:  more.
                   1036: */
                   1037: VOID
                   1038: rcalcpsz() {
                   1039: 
                   1040: #ifdef COMMENT
                   1041: /* Old way */
                   1042:     register long x, q;
                   1043:     if (numerrs == 0) return;  /* bounds check just in case */
                   1044: 
                   1045:     /* overhead on a data packet is npad+5+bctr, plus 3 if extended packet */
                   1046:     /* an ACK is 5+bctr */
                   1047: 
                   1048:     /* first set x = per packet overhead */
                   1049:     if (wslots > 1)
                   1050:        x = (long) (npad+5+bctr);    /* only the packet, don't count the ack */
                   1051:     else
                   1052:        x = (long) (npad+5+3+bctr+5+bctr);
                   1053: 
                   1054:     /* then set x = packet length ** 2 */
                   1055:     x = x * ( ffc / (long) numerrs);   /* careful of overflow */
                   1056:     
                   1057:     /* calculate the long integer sqrt(x) quickly */
                   1058:     q = 500;
                   1059:     q = (q + x/q) >> 1;
                   1060:     q = (q + x/q) >> 1;
                   1061:     q = (q + x/q) >> 1;
                   1062:     q = (q + x/q) >> 1;                /* should converge in about 4 steps */
                   1063:     if ((q > 94) && (q < 130)) /* break-even point for long packets */
                   1064:        q = 94;
                   1065:     if (q > spmax) q = spmax;  /* maximum bounds */
                   1066:     if (q < 10) q = 10;                /* minimum bounds */
                   1067:     spsiz = q;                 /* set new send packet size */
                   1068:     debug(F101,"rcalcpsiz","",q);
                   1069: #else
                   1070: /* New way */
                   1071:     if (spackets < 3) return;
                   1072:     debug(F101,"rcalcpsiz numerrs","",numerrs);
                   1073:     debug(F101,"rcalcpsiz spsiz","",spsiz);
                   1074:     if (numerrs)
                   1075:       spsiz = spsiz / 2;
                   1076:     else
                   1077:       spsiz = (spsiz / 4) * 5;
                   1078:     if (spsiz < 20) spsiz = 20;
                   1079:     if (spsiz > spmax) spsiz = spmax;
                   1080:     debug(F101,"rcalcpsiz new spsiz","",spsiz);
                   1081:     numerrs = 0;
                   1082:     return;
                   1083: #endif
                   1084: }
                   1085: 
                   1086: /*  R E S E N D  --  Retransmit packet n.  */
                   1087: 
                   1088: /* Returns 0 or positive on success. */
                   1089: /* On failure, returns a negative number, and an error message is placed */
                   1090: /* in recpkt.  All errors are considered fatal.  */
                   1091: 
                   1092: #ifdef IOFATAL
                   1093: #undef IOFATAL
                   1094: #endif
                   1095: /*
                   1096:   Let's try something new...  I/O errors are not fatal.  Let retry mechanisms
                   1097:   take care of giving up (edit 159).
                   1098: */
                   1099: int
                   1100: resend(n) int n; {                     /* Send packet n again. */
                   1101:     int k;
                   1102: 
                   1103:     debug(F101,"resend seq","",n);
                   1104:     if ((k = chkwin(n,winlo,wslots)) != 0) { /* Check if it's in the window */
                   1105:        debug(F101,"resend pkt not in win","",k);
                   1106:        if (nakstate && k == 1) {       /* Take a chance... */
                   1107: #ifdef IOFATAL
                   1108:            if (spack('Y',n,0,(CHAR *) "") < 0) { /* Send an ACK... */
                   1109:                debug(F100,"resend spack fails","",0);
                   1110:                sprintf((char *)recpkt,
                   1111:                        "resend i/o error: SPF, n=%d, k=%d.",n,k);
                   1112:                return(-2);
                   1113:            }
                   1114:            debug(F101,"resent ACK from prev window ok","",n);
                   1115: #else
                   1116:            spack('Y',n,0,(CHAR *) ""); /* Just send the ACK... */
                   1117: #endif /* IOFATAL */
                   1118:            retrans++;
                   1119:            return(0);
                   1120:        } else {
                   1121:            debug(F100,"resend pkt not in window","",0);
                   1122:            sprintf((char *)recpkt,"resend error: NIW, n=%d, k=%d.",n,k);
                   1123:            return(-2);
                   1124:        }
                   1125:     }
                   1126:     k = sseqtbl[n];                    /* OK, it's in the window. */
                   1127:     debug(F101,"resend pktinfo index","",k);
                   1128:     if (k < 0) {                       /* But I can't find it! */
                   1129:        debug(F101,"resend sseqtbl failure for pkt","",n);
                   1130:        sprintf((char *)recpkt,"resend logic error: BPX, n=%d, k=%d.",n,k);
                   1131:        return(-2);
                   1132:     }
                   1133:     if (s_pkt[k].pk_rtr++ > maxtry) {  /* Found it but over retry limit */
                   1134:        strcpy((char *)recpkt,"Too many retries.");
                   1135:        return(-1);
                   1136:     }
                   1137:     debug(F101," retry","",s_pkt[k].pk_rtr); /* OK so far */
                   1138:     dumpsbuf();
                   1139:     if (s_pkt[k].pk_typ == ' ') {      /* Incompletely formed packet */
                   1140:        if (nakstate) {                 /* (This shouldn't happen any more) */
                   1141:            nack(n);
                   1142:            retrans++;
                   1143:            return(s_pkt[k].pk_rtr);
                   1144:        } else {                        /* No packet to resend! */
                   1145:            sprintf((char *)recpkt,
                   1146:                    "resend logic error: NPS, n=%d, k=%d.",n,k); 
                   1147:            return(-2);
                   1148:        }
                   1149:     }
                   1150: #ifdef IOFATAL
                   1151:     if (ttol(s_pkt[k].pk_adr,s_pkt[k].pk_len) < 0) {
                   1152:        debug(F100,"resend ttol failed","",0);
                   1153:        sprintf((char *)recpkt,"resend i/o error: TIO, n=%d, k=%d.",n,k);
                   1154:        return(-2);
                   1155:     }
                   1156: #else
                   1157:     ttol(s_pkt[k].pk_adr,s_pkt[k].pk_len);
                   1158: #endif /* IOFATAL */
                   1159:     retrans++;
                   1160:     screen(SCR_PT,'%',(long)pktnum,"(resend)");        /* Say resend occurred */
                   1161:     logpkt('S',n,s_pkt[k].pk_adr);     /* Log packet */
                   1162:     return(s_pkt[k].pk_rtr);           /* Return retries. */
                   1163: }
                   1164: 
                   1165: int
                   1166: errpkt(reason) CHAR *reason; {         /* Send an error packet. */
                   1167:     int x, y;
                   1168:     encstr(reason);
                   1169:     y = spack('E',pktnum,size,encbuf+7);
                   1170:     x = quiet; quiet = 1;              /* Close files silently. */
                   1171:     clsif(); clsof(1);
                   1172:     quiet = x;
                   1173:     screen(SCR_TC,0,0l,"");
                   1174:     if (what < W_CONNECT)
                   1175:       xitsta |= what;                  /* Remember what failed. */
                   1176:     success = 0;
                   1177:     return(y);
                   1178: }
                   1179: 
                   1180: /* scmd()  --  Send a packet of the given type */
                   1181: 
                   1182: int
                   1183: #ifdef CK_ANSIC
                   1184: scmd(char t, CHAR *dat)
                   1185: #else
                   1186: scmd(t,dat) char t; CHAR *dat;
                   1187: #endif /* CK_ANSIC */
                   1188: /* scmd */ {
                   1189:     encstr(dat);                       /* Encode the command string */
                   1190:     spack(t,pktnum,size,(CHAR *)(encbuf+7));
                   1191:     return(0);
                   1192: }
                   1193: 
                   1194: VOID
                   1195: srinit() {                             /* Send R (GET) packet */
                   1196:     encstr((CHAR *)cmarg);             /* Encode the filename. */
                   1197:     spack('R',pktnum,size,encbuf+7);   /* Send the packet. */
                   1198: }
                   1199: 
                   1200: /* R P A C K  --  Read a Packet */
                   1201: 
                   1202: /*
                   1203:  rpack reads a packet and returns the packet type, or else Q if the
                   1204:  packet was invalid, or T if a timeout occurred.  Upon successful return, sets
                   1205:  the values of global rsn (received sequence number),  rln (received
                   1206:  data length), and rdatap (pointer to null-terminated data field).
                   1207: */
                   1208: int
                   1209: rpack() {
                   1210:     register int i, j, x, lp;          /* Local variables */
                   1211:     int k, type, chklen;
                   1212:     unsigned crc;
                   1213:     CHAR pbc[4];                       /* Packet block check */
                   1214:     CHAR *sohp;                                /* Pointer to SOH */
                   1215:     CHAR e;                            /* Packet end character */
                   1216: 
                   1217:     debug(F101,"entering rpack, pktnum","",pktnum);
                   1218:     k = getrbuf();                     /* Get a new packet input buffer. */
                   1219:     debug(F101,"rpack getrbuf","",k);
                   1220:     if (k < 0) return(-1);             /* Return like this if none free. */
                   1221:     recpkt = r_pkt[k].bf_adr;
                   1222:     *recpkt = '\0';                    /* Clear receive buffer. */
                   1223:     sohp = recpkt;                     /* Initialize pointers to it. */
                   1224:     rdatap = recpkt;
                   1225:     rsn = rln = -1;                    /* In case of failure. */
                   1226:     e = (turn) ? turnch : eol;         /* Use any handshake char for eol */
                   1227: 
                   1228: /* Try to get a "line". */
                   1229: 
                   1230: #ifdef PARSENSE
                   1231: #ifdef UNIX
                   1232: /*
                   1233:   So far the final turn argument is only ckutio.c.  Should be added
                   1234:   to the others too.
                   1235: */
                   1236:     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e,stchr,turn);
                   1237: #else
                   1238:     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e,stchr);
                   1239: #endif /* UNIX */
                   1240:     if (parity != ttprty) autopar = 1;
                   1241:     parity = ttprty; 
                   1242: #else
                   1243:     j = ttinl(recpkt,r_pkt[k].bf_len - 1,timint,e);
                   1244: #endif
                   1245:     if (j < 0) {
                   1246:        debug(F101,"rpack: ttinl fails","",j); /* Otherwise, */
                   1247:        freerbuf(k);                    /* Free this buffer */
                   1248:        if (j < -1) {                   /* Bail out if ^C^C typed. */
                   1249:            debug(F101,"rpack ^C server","",server);
                   1250:            debug(F101,"rpack ^C en_fin","",en_fin);
                   1251:            if (server == 0) return(j); /* But not if in server mode */
                   1252:            else if (en_fin) return(j); /* with DISABLE FINISH */
                   1253:        }
                   1254:        if (nakstate)                          /* call it a timeout. */
                   1255:          screen(SCR_PT,'T',(long)winlo,"");
                   1256:        else
                   1257:          screen(SCR_PT,'T',(long)pktnum,"");
                   1258:        logpkt('r',-1,(CHAR *)"<timeout>");
                   1259:        if (flow == 1) ttoc(XON);       /* In case of Xoff blockage. */
                   1260:        return('T');
                   1261:     }
                   1262:     tlci += j;                         /* All OK, Count the characters. */
                   1263:     flci += j;
                   1264: 
                   1265: #ifndef PARSENSE
                   1266: /* THEN eliminate this loop... */
                   1267:     for (i = 0; (recpkt[i] != stchr) && (i < j); i++)
                   1268:       sohp++;                          /* Find mark */
                   1269:     if (i++ >= j) {                    /* Didn't find it. */
                   1270:        logpkt('r',-1,"<timeout>");
                   1271:        freerbuf(k);
                   1272:        return('T');
                   1273:     }    
                   1274: #else
                   1275:     i = 1;
                   1276: #endif /* PARSENSE */
                   1277: 
                   1278:     rpackets++;
                   1279:     lp = i;                            /* Remember LEN position. */
                   1280:     if ((j = xunchar(recpkt[i++])) == 0) {
                   1281:         if ((j = lp+5) > MAXRP) return('Q'); /* Long packet */
                   1282:        x = recpkt[j];                  /* Header checksum. */
                   1283:        recpkt[j] = '\0';               /* Calculate & compare. */
                   1284:        if (xunchar(x) != chk1(recpkt+lp)) {
                   1285:            freerbuf(k);
                   1286:            logpkt('r',-1,(CHAR *)"<crunched:hdr>");
                   1287:            return('Q');
                   1288:        }
                   1289:        recpkt[j] = x;                  /* Checksum ok, put it back. */
                   1290:        rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctu;
                   1291:        j = 3;                          /* Data offset. */
                   1292:     } else if (j < 3) {
                   1293:        debug(F101,"rpack packet length less than 3","",j);
                   1294:        freerbuf(k);
                   1295:        logpkt('r',-1,(CHAR *)"<crunched:len>");
                   1296:        return('Q');
                   1297:     } else {
                   1298:        rln = j - bctu - 2;             /* Regular packet */
                   1299:        j = 0;                          /* No extended header */
                   1300:     }
                   1301:     rsn = xunchar(recpkt[i++]);                /* Sequence number */
                   1302:     logpkt('r',rsn,sohp);
                   1303:     if (rsn < 0 || rsn > 63) {
                   1304:        debug(F101,"rpack bad sequence number","",rsn);
                   1305:        freerbuf(k);
                   1306:        logpkt('r',rsn,(CHAR *)"<crunched:seq>");
                   1307:        return('Q');
                   1308:     }
                   1309:     type = recpkt[i++];                        /* Packet type */
                   1310: #define XXX
                   1311: #ifdef XXX
                   1312: /*
                   1313:     Heuristics to adjust for old block-check type on retransmitted packet
                   1314:     after block check has switched.
                   1315: */
                   1316:     if (type == 'I' || type == 'S') {  /* These always have type 1 */
                   1317:        chklen = 1;
                   1318:        rln = rln + bctu - 1;
                   1319:     } else if (type == 'N') {          /* NAK never has data */
                   1320:        chklen = xunchar(recpkt[lp]) - 2;
                   1321:        rln = rln + bctu - chklen;
                   1322:     } else chklen = bctu;
                   1323: #else
                   1324:     chklen = bctu;
                   1325: #endif /* XXX */
                   1326:     i += j;                            /* Where data begins */
                   1327:     rdatap = recpkt+i;                 /* The data itself */
                   1328:     if ((j = rln + i) > r_pkt[k].bf_len ) {
                   1329:        debug(F101,"packet sticks out too far","",j);
                   1330:        freerbuf(k);
                   1331:        logpkt('r',rsn,(CHAR *)"<overflow>");
                   1332:        return('Q');
                   1333:     }
                   1334:     for (x = 0; x < chklen; x++)       /* Copy out the block check */
                   1335:       pbc[x] = recpkt[j+x];
                   1336:     pbc[x] = '\0';                     /* Null-terminate block check string */
                   1337:     recpkt[j] = '\0';                  /*  and the packet data. */
                   1338:     debug(F101,"rpack chklen","",chklen);
                   1339: 
                   1340:     switch (chklen) {                  /* Check the block check */
                   1341:        case 1:
                   1342:            if (xunchar(*pbc) != chk1(recpkt+lp)) {
                   1343:                debug(F110,"checked chars",recpkt+lp,0);
                   1344:                debug(F101,"block check","",(int) xunchar(*pbc));
                   1345:                debug(F101,"should be","",chk1(recpkt+lp));
                   1346:                freerbuf(k);
                   1347:                logpkt('r',-1,(CHAR *)"<crunched:chk1>");
                   1348:                return('Q');
                   1349:            }
                   1350:            break;
                   1351:        case 2:
                   1352:            x = xunchar(*pbc) << 6 | xunchar(pbc[1]);
                   1353:            if (x != chk2(recpkt+lp)) {
                   1354:                debug(F110,"checked chars",recpkt+lp,0);
                   1355:                debug(F101,"block check","", x);
                   1356:                debug(F101,"should be","", (int) chk2(recpkt+lp));
                   1357:                freerbuf(k);
                   1358:                logpkt('r',-1,(CHAR *)"<crunched:chk2>");
                   1359:                return('Q');
                   1360:            }
                   1361:            break;
                   1362:        case 3:
                   1363:            crc = (xunchar(pbc[0]) << 12)
                   1364:                | (xunchar(pbc[1]) << 6)
                   1365:                | (xunchar(pbc[2]));
                   1366:            if (crc != chk3(recpkt+lp)) {
                   1367:                debug(F110,"checked chars",recpkt+lp,0);
                   1368:                debug(F101,"block check","",xunchar(*pbc));
                   1369:                debug(F101,"should be","",(int) chk3(recpkt+lp));
                   1370:                freerbuf(k);
                   1371:                logpkt('r',-1,(CHAR *)"<crunched:chk3>");
                   1372:                return('Q');
                   1373:            }
                   1374:            break;
                   1375:        default:                        /* Shouldn't happen... */
                   1376:            freerbuf(k);
                   1377:            logpkt('r',-1,(CHAR *)"<crunched:chkx>");
                   1378:            return('Q');
                   1379:     }
                   1380:     debug(F101,"rpack block check OK","",rsn);
                   1381: 
                   1382: /* Now we can believe the sequence number, etc. */
                   1383: /* Here we violate strict principles of layering, etc, and look at the  */
                   1384: /* packet sequence number.  If there's already a packet with the same   */
                   1385: /* number in the window, we remove this one so that the window will not */
                   1386: /* fill up. */
                   1387: 
                   1388:     if ((x = rseqtbl[rsn]) != -1) {    /* Already a packet with this number */
                   1389:        retrans++;                      /* Count it for statistics */
                   1390:        debug(F101,"rpack got dup","",rsn);
                   1391:        logpkt('r',rsn,(CHAR *)"<duplicate>");
                   1392:        freerbuf(x);                    /* Free old buffer, keep new packet. */
                   1393:        r_pkt[k].pk_rtr++;              /* Count this as a retransmission. */
                   1394:     }
                   1395: 
                   1396: /* New packet, not seen before, enter it into the "database". */
                   1397: 
                   1398:     rseqtbl[rsn] = k;                  /* Make back pointer */
                   1399:     r_pkt[k].pk_seq = rsn;             /* Record in packet info structure */
                   1400:     r_pkt[k].pk_typ = type;            /* Sequence, type,... */
                   1401:     r_pkt[k].pk_adr = rdatap;          /* pointer to data buffer */
                   1402:     screen(SCR_PT,(char)type,(long)rsn,(char *)sohp); /* Update screen */
                   1403:     return(type);                      /* Return packet type */
                   1404: }
                   1405: 
                   1406: /*  L O G P K T  --  Log packet number n, pointed to by s.  */
                   1407: 
                   1408: /* c = 's' (send) or 'r' (receive) */
                   1409: 
                   1410: VOID
                   1411: #ifdef CK_ANSIC
                   1412: logpkt(char c,int n, CHAR *s)
                   1413: #else
                   1414: logpkt(c,n,s) char c; int n; CHAR *s;
                   1415: #endif /* CK_ANSIC */
                   1416: /* logpkt */ {
                   1417:     char plog[20];
                   1418:     if (pktlog && *s) {
                   1419:        if (n < 0)
                   1420:          sprintf(plog,"%c-xx-%02d-",c,(gtimer()%60));
                   1421:        else
                   1422:          sprintf(plog,"%c-%02d-%02d-",c,n,(gtimer()%60));
                   1423:        if (zsout(ZPFILE,plog) < 0) pktlog = 0;
                   1424:        else if (zsoutl(ZPFILE,(char *)s) < 0) pktlog = 0;
                   1425:     }
                   1426: }
                   1427: 
                   1428: #ifdef TLOG
                   1429: 
                   1430: /*  T S T A T S  --  Record statistics in transaction log  */
                   1431: 
                   1432: VOID
                   1433: tstats() {
                   1434:     char *tp;
                   1435:     ztime(&tp);                                /* Get time stamp */
                   1436:     tlog(F110,"End of transaction",tp,0L);  /* Record it */
                   1437: 
                   1438:     if (filcnt < 1) return;            /* If no files, done. */
                   1439: 
                   1440: /* If multiple files, record character totals for all files */
                   1441: 
                   1442:     if (filcnt > 1) {
                   1443:        tlog(F101," files","",filcnt);
                   1444:        tlog(F101," total file characters   ","",tfc);
                   1445:        tlog(F101," communication line in   ","",tlci);
                   1446:        tlog(F101," communication line out  ","",tlco);
                   1447:     }
                   1448: 
                   1449: /* Record timing info for one or more files */
                   1450: 
                   1451:     tlog(F101," elapsed time (seconds)  ","",(long) tsecs);
                   1452:     if (tsecs > 0) {
                   1453:        long lx;
                   1454:        lx = (tfc * 10L) / (long) tsecs;
                   1455:        tlog(F101," effective data rate     ","",lx/10L);
                   1456:        if (speed <= 0L) speed = ttgspd();
                   1457:        if (speed > 0L && speed != 8880L && network == 0) {
                   1458:            lx = (lx * 100L) / speed;
                   1459:            tlog(F101," efficiency (percent)    ","",lx);
                   1460:        }
                   1461:     }
                   1462:     tlog(F100,"","",0L);               /* Leave a blank line */
                   1463: }
                   1464: 
                   1465: /*  F S T A T S  --  Record file statistics in transaction log  */
                   1466: 
                   1467: VOID
                   1468: fstats() {
                   1469:     tfc += ffc;
                   1470:     tlog(F100," end of file","",0L);
                   1471:     tlog(F101,"  file characters        ","",ffc);
                   1472:     tlog(F101,"  communication line in  ","",flci);
                   1473:     tlog(F101,"  communication line out ","",flco);
                   1474: }
                   1475: #else /* NOTLOG */
                   1476: VOID
                   1477: tstats() {}
                   1478: 
                   1479: VOID
                   1480: fstats() {
                   1481:     tfc += ffc;
                   1482: }
                   1483: #endif /* TLOG */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.