📄 ckcfn2.c
字号:
/* C K C F N 2 -- System-independent Kermit protocol support functions... *//* ...Part 2 (continued from ckcfns.c) *//* Author: Frank da Cruz (fdc@watsun.cc.columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. First released January 1985. Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use this software as long as it is not sold for profit. This copyright notice must be retained. This software may not be included in commercial products without written permission of Columbia University.*//* Note -- if you change this file, please amend the version number and date at the top of ckcfns.c accordingly.*/#include "ckcsym.h" /* Compilation options */#include "ckcdeb.h" /* Debugging and other symbols */#include "ckcasc.h" /* ASCII symbols */#include "ckcker.h" /* Kermit symbols */#include "ckcxla.h" /* Translation */#ifdef TCPSOCKET /* For TELNET business in spack() */#ifndef NP_TELNET#define NP_TELNET 1extern int tn_nlm, ttnproto;#endif /* NP_TELNET */#endif /* TCPSOCKET */#ifdef DYNAMICextern struct pktinfo *s_pkt; /* array of pktinfo structures */extern struct pktinfo *r_pkt; /* array of pktinfo structures */#elseextern struct pktinfo s_pkt[]; /* array of pktinfo structures */extern struct pktinfo r_pkt[]; /* array of pktinfo structures */#endif /* DYNAMIC */extern int sseqtbl[], rseqtbl[], sbufuse[], sacktbl[], wslots, winlo, sbufnum;extern int ttprty; /* from ckutio.c */extern int autopar;extern int spsiz, spmax, rpsiz, timint, timef, npad, ebq, ebqflg;extern int rpt, rptq, rptflg, capas, spsizf, en_fin, tsecs, network, flow;extern int pktnum, sndtyp, bctr, bctu, bctl, rsn, rln, maxtry, size;extern int osize, maxsize, spktl, rpktl, nfils, stdouf, warn, parity;extern int turn, turnch, delay, displa, pktlog, tralog, seslog, xflg, mypadn;extern int hcflg, local, server, cxseen, czseen;extern int nakstate, quiet, success, xitsta, what;extern int spackets, rpackets, timeouts, retrans, crunched, urpsiz;extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, speed;extern char *cmarg, *cmarg2, filnam[], *hlptxt;extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate;extern CHAR *recpkt, *data, encbuf[], myinit[];extern CHAR *srvptr, stchr, mystch, *rdatap;extern CHAR padbuf[];#ifdef DYNAMIC extern CHAR *srvcmd;#else extern CHAR srvcmd[];#endif /* DYNAMIC */int numerrs = 0; /* (PWP) total number packet errors so far */static CHAR partab[] = { /* Even parity table for dopar(). */ (CHAR) '\000', /* ANSI C casts '\ooo' constants */ (CHAR) '\201', /* to signed char, so we have to */ (CHAR) '\202', /* cast back to unsigned char... */ (CHAR) '\003', (CHAR) '\204', (CHAR) '\005', (CHAR) '\006', (CHAR) '\207', (CHAR) '\210', (CHAR) '\011', (CHAR) '\012', (CHAR) '\213', (CHAR) '\014', (CHAR) '\215', (CHAR) '\216', (CHAR) '\017', (CHAR) '\220', (CHAR) '\021', (CHAR) '\022', (CHAR) '\223', (CHAR) '\024', (CHAR) '\225', (CHAR) '\226', (CHAR) '\027', (CHAR) '\030', (CHAR) '\231', (CHAR) '\232', (CHAR) '\033', (CHAR) '\234', (CHAR) '\035', (CHAR) '\036', (CHAR) '\237', (CHAR) '\240', (CHAR) '\041', (CHAR) '\042', (CHAR) '\243', (CHAR) '\044', (CHAR) '\245', (CHAR) '\246', (CHAR) '\047', (CHAR) '\050', (CHAR) '\251', (CHAR) '\252', (CHAR) '\053', (CHAR) '\254', (CHAR) '\055', (CHAR) '\056', (CHAR) '\257', (CHAR) '\060', (CHAR) '\261', (CHAR) '\262', (CHAR) '\063', (CHAR) '\264', (CHAR) '\065', (CHAR) '\066', (CHAR) '\267', (CHAR) '\270', (CHAR) '\071', (CHAR) '\072', (CHAR) '\273', (CHAR) '\074', (CHAR) '\275', (CHAR) '\276', (CHAR) '\077', (CHAR) '\300', (CHAR) '\101', (CHAR) '\102', (CHAR) '\303', (CHAR) '\104', (CHAR) '\305', (CHAR) '\306', (CHAR) '\107', (CHAR) '\110', (CHAR) '\311', (CHAR) '\312', (CHAR) '\113', (CHAR) '\314', (CHAR) '\115', (CHAR) '\116', (CHAR) '\317', (CHAR) '\120', (CHAR) '\321', (CHAR) '\322', (CHAR) '\123', (CHAR) '\324', (CHAR) '\125', (CHAR) '\126', (CHAR) '\327', (CHAR) '\330', (CHAR) '\131', (CHAR) '\132', (CHAR) '\333', (CHAR) '\134', (CHAR) '\335', (CHAR) '\336', (CHAR) '\137', (CHAR) '\140', (CHAR) '\341', (CHAR) '\342', (CHAR) '\143', (CHAR) '\344', (CHAR) '\145', (CHAR) '\146', (CHAR) '\347', (CHAR) '\350', (CHAR) '\151', (CHAR) '\152', (CHAR) '\353', (CHAR) '\154', (CHAR) '\355', (CHAR) '\356', (CHAR) '\157', (CHAR) '\360', (CHAR) '\161', (CHAR) '\162', (CHAR) '\363', (CHAR) '\164', (CHAR) '\365', (CHAR) '\366', (CHAR) '\167', (CHAR) '\170', (CHAR) '\371', (CHAR) '\372', (CHAR) '\173', (CHAR) '\374', (CHAR) '\175', (CHAR) '\176', (CHAR) '\377'};/* CRC generation tables */static long crcta[16] = { 0L, 010201L, 020402L, 030603L, 041004L, 051205L, 061406L, 071607L, 0102010L, 0112211L, 0122412L, 0132613L, 0143014L, 0153215L, 0163416L, 0173617L };static long crctb[16] = { 0L, 010611L, 021422L, 031233L, 043044L, 053655L, 062466L, 072277L, 0106110L, 0116701L, 0127532L, 0137323L, 0145154L, 0155745L, 0164576L, 0174367L };/* I N P U T -- Attempt to read packet number 'pktnum'. *//* This is the function that feeds input to Kermit's finite state machine, in the form of a character in the range 32-126, normally a packet type (uppercase letter) or pseudo-packet-type (lowercase letter). If a special start state is in effect, that state is returned as if it were the type of an incoming packet. Otherwise: (fill in...)*/intinput() { int type; int x = 0, y, k; debug(F101,"input sstate","",sstate); debug(F101," nakstate","",nakstate); debug(F000," sndtyp","",sndtyp); while (1) { /* Big loop... */ if (sstate != 0) { /* If a start state is in effect, */ type = sstate; /* return it like a packet type, */ sstate = 0; /* and then nullify it. */ numerrs = 0; /* (PWP) no errors so far */ return(type); } if (nakstate) { /* This section for file receiver. */ if (wslots > 1) { /* If we're doing windows, */ x = rseqtbl[winlo]; /* see if desired packet already in. */ debug(F101," winlo","",winlo); debug(F101," rseqtbl[winlo]","",rseqtbl[winlo]); if (x > -1) { /* Already there? */ if (r_pkt[x].pk_seq == winlo) { /* (double check) */ rsn = winlo; /* Yes, return its info */ debug(F101,"input return pre-stashed packet","",rsn); dumprbuf(); rdatap = r_pkt[x].pk_adr; /* like rpack would do. */ rln = (int)strlen((char *) rdatap); type = r_pkt[x].pk_typ; break; } } } type = rpack(); /* Try to read a packet. */ debug(F111,"input recv",(char *) rdatap,(int) type); while (type == 'e') { /* Handle echoes */ debug(F000,"echo discarded","",type); type = rpack(); } if (type < -1) return('q'); /* Ctrl-C */ if (type < 0) { /* Receive window full */ /* Another thing to do here would be to delete */ /* the highest packet and NAK winlo. But that */ /* shouldn't be necessary since the other Kermit */ /* should not have sent a packet outside the window. */ debug(F101,"rpack receive window full","",0); dumprbuf(); errpkt((CHAR *)"Receive window full."); strcpy((char *)recpkt,"Receive window full."); type = 'E'; break; } dumprbuf(); if (chkint() < 0) { /* Check for console interrupts. */ errpkt((CHAR *)"User cancelled."); strcpy((char *)recpkt,"User cancelled."); type = 'E'; break; } if (type == 'E') { debug(F101,"input got E, nakstate","",nakstate); break; /* Error packet */ } if (type == 'Q') { /* Crunched packet. */ crunched++; numerrs++; if (nack(winlo) < 0) { /* Request resend of window-low.. */ debug(F101,"input sent too many naks","",winlo); errpkt((CHAR *)"Too many retries."); strcpy((char *)recpkt,"Sent too many NAKs."); type = 'E'; break; } else continue; } if (type == 'T') { /* Timeout */#ifdef BULKNAKS int z;#endif timeouts++; debug(F101,"input receive-state timeout, winlo","",winlo);#ifdef BULKNAKS z = winlo + wslots; /* NAK all unACK'd packets */ if (z > 63) z -= 64; debug(F101,"input sending bulk NAKs, winlo","",winlo); for (x = winlo; (x != z) && ttchk() == 0; x++) { if (x < 0 || x > 63) break; if (rseqtbl[x] < 0) { if (nack(x) < 0) { debug(F101,"input sent too many naks","",winlo); errpkt((CHAR *)"Too many retries."); strcpy(recpkt,"Sent too many NAKs."); type = 'E'; break; } } }#else /* NAK only the packet at window-low */ debug(F101,"input sending NAK for winlo","",winlo); if (nack(winlo) < 0) { debug(F101,"input sent too many naks","",winlo); errpkt((CHAR *)"Too many retries."); strcpy((char *)recpkt,"Sent too many NAKs."); type = 'E'; break; }#endif /* BULKNAKS */ continue; } /* Got the packet we want, done. */ if (rsn == winlo) { debug(F101,"input rsn=winlo","",rsn); break; } /* Got a packet out of order. */ debug(F101,"input recv got packet out of order","",rsn); k = rseqtbl[rsn]; /* Get window slot of this packet. */ debug(F101,"input recv rseqtbl[rsn]","",k); if (k < 0) { debug(F101,"input recv can't find index for rcvd pkt","",rsn); errpkt((CHAR *)"internal error number 21"); strcpy((char *)recpkt,"Sliding windows protocol error."); type = 'E'; break; } y = chkwin(rsn,winlo,wslots); /* See what window it's in. */ debug(F101,"input recv chkwin","",y); if (y == 1) { /* Previous window. */#ifdef COMMENT ackn(rsn); /* Send empty ACK */#else resend(rsn);#endif /* COMMENT */ freerpkt(rsn); /* Get rid of received packet */ continue; } else { /* In this window or out of range */ if (y < 0) /* If out of range entirely, */ freerpkt(rsn); /* release its buffer *//* We have received a packet, but not the one we want. If we do nothing, we could be in for a lengthy timeout/retry cycle. It would seem to make sense to send a NAK for the most desired packet (winlo). But consider this scenario: a packet arrived damaged so we NAK'd it above; then packets winlo+1, winlo+2, ... winlo+n arrive, each one making us send a NAK for winlo, so the other Kermit gets n NAKs for winlo, and either would have to resend it n times, or if n > retry limit, give up because of too many retries. So we compromise: If a packet arrives that is not the most desired packet (winlo), we NAK winlo, BUT ONLY IF it has not been NAK'd before.*/ if (s_pkt[k].pk_rtr == 0) { /* Have we been here before? */ if (nack(winlo) < 0) { /* No, NAK winlo. */ errpkt((CHAR *)"Too many retries."); /* Too many */ strcpy((char *)recpkt,"Timed out."); /* Give up */ type = 'E'; break; } else continue; } else continue; }/*!!!*/ } else { /* Otherwise file sender... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -