source: trunk/third/kermit/ckcfn2.c @ 10780

Revision 10780, 66.4 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10779, which included commits to RCS files with non-trunk default branches.
Line 
1#define NEWDPL
2
3/*  C K C F N 2  --  System-independent Kermit protocol support functions... */
4
5/*  ...Part 2 (continued from ckcfns.c)  */
6
7/*
8  Author: Frank da Cruz <fdc@columbia.edu>,
9  Columbia University Academic Information Systems, New York City.
10
11  Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New
12  York.  The C-Kermit software may not be, in whole or in part, licensed or
13  sold for profit as a software product itself, nor may it be included in or
14  distributed with commercial products or otherwise distributed by commercial
15  concerns to their clients or customers without written permission of the
16  Office of Kermit Development and Distribution, Columbia University.  This
17  copyright notice must not be removed, altered, or obscured.
18*/
19/*
20 Note -- if you change this file, please amend the version number and date at
21 the top of ckcfns.c accordingly.
22*/
23
24#include "ckcsym.h"                     /* Compilation options */
25#include "ckcdeb.h"                     /* Debugging and other symbols */
26#include "ckcasc.h"                     /* ASCII symbols */
27#include "ckcker.h"                     /* Kermit symbols */
28#include "ckcxla.h"                     /* Translation */
29
30#ifdef TCPSOCKET                        /* For TELNET business in spack() */
31#ifndef NP_TELNET                       /* Avoid dragging in ckcnet.h */
32#define NP_TELNET  1
33#define TNL_CR     0                    /* CR sends bare carriage return */
34#define TNL_CRNUL  1                    /* CR and NUL */
35#define TNL_CRLF   2                    /* CR and LF */
36#define TNL_LF     3                    /* LF instead of CR */
37#endif /* NP_TELNET */
38extern int tn_nlm, ttnproto;
39extern int me_binary, tn_b_nlm;
40#endif /* TCPSOCKET */
41
42#ifdef DYNAMIC
43extern struct pktinfo *s_pkt;           /* array of pktinfo structures */
44extern struct pktinfo *r_pkt;           /* array of pktinfo structures */
45#else
46extern struct pktinfo s_pkt[];          /* array of pktinfo structures */
47extern struct pktinfo r_pkt[];          /* array of pktinfo structures */
48#endif /* DYNAMIC */
49
50extern int sseqtbl[], rseqtbl[], sbufuse[], sacktbl[], wslots, winlo,
51  sbufnum, rbufnum, pktpaus;
52
53extern int ttprty;                      /* from ck*tio.c */
54extern int autopar;
55
56extern int spsiz, spmax, rpsiz, timint, timef, npad, bestlen, maxsend;
57extern int rpt, rptq, rptflg, capas, spsizf, en_fin, tsecs, network, flow;
58extern int pktnum, sndtyp, rcvtyp, bctr, bctu, bctl, rsn, rln, maxtry, size;
59extern int osize, maxsize, spktl, rpktl, nfils, stdouf, warn, parity;
60extern int turn, turnch,  delay, displa, pktlog, tralog, seslog, xflg, mypadn;
61extern int hcflg, local, server, cxseen, czseen, discard, slostart;
62extern int nakstate, quiet, success, xitsta, what;
63extern int spackets, rpackets, timeouts, retrans, crunched, urpsiz;
64
65extern long filcnt, filrej, ffc, flci, flco, tlci, tlco, tfc, speed;
66
67extern char *cmarg, filnam[], *hlptxt;
68
69extern CHAR padch, mypadc, eol, seol, ctlq, sstate;
70extern CHAR *recpkt, *data, myinit[];
71extern CHAR *srvptr, stchr, mystch, *rdatap;
72extern CHAR padbuf[];
73#ifdef pdp11
74  extern CHAR srvcmd[];
75  extern CHAR *pktmsg;
76#else
77#ifdef DYNAMIC
78  extern CHAR *srvcmd;
79  extern CHAR *pktmsg;
80#else
81  extern CHAR srvcmd[];
82  extern CHAR pktmsg[];
83#endif /* DYNAMIC */
84#endif /* pdp11 */
85
86int numerrs = 0;                        /* Number of packet errors so far */
87int rcvtimo = 0;                        /* Timeout for receiving a packet */
88
89#ifdef CK_TIMERS
90int rrttbl[64], srttbl[64];             /* Packet timestamp tables */
91extern int rttflg;
92#define RTT_SCALE 1000
93long
94  rttsamples,                           /* Round trip time samples */
95  rttdelay,                             /* RTT delay */
96  pktintvl,                             /* Interpacket arrival time */
97  rttvariance,                          /* RTT variance */
98  rttstddev;                            /* RTT standard deviation */
99#endif /* CK_TIMERS */
100
101static CHAR p_tbl[] = {                 /* Even parity table for dopar(). */
102    (CHAR) '\000',                      /* ANSI C casts '\ooo' constants  */
103    (CHAR) '\201',                      /* to signed char, so we have to  */
104    (CHAR) '\202',                      /* cast back to unsigned char...  */
105    (CHAR) '\003',
106    (CHAR) '\204',
107    (CHAR) '\005',
108    (CHAR) '\006',
109    (CHAR) '\207',
110    (CHAR) '\210',
111    (CHAR) '\011',
112    (CHAR) '\012',
113    (CHAR) '\213',
114    (CHAR) '\014',
115    (CHAR) '\215',
116    (CHAR) '\216',
117    (CHAR) '\017',
118    (CHAR) '\220',
119    (CHAR) '\021',
120    (CHAR) '\022',
121    (CHAR) '\223',
122    (CHAR) '\024',
123    (CHAR) '\225',
124    (CHAR) '\226',
125    (CHAR) '\027',
126    (CHAR) '\030',
127    (CHAR) '\231',
128    (CHAR) '\232',
129    (CHAR) '\033',
130    (CHAR) '\234',
131    (CHAR) '\035',
132    (CHAR) '\036',
133    (CHAR) '\237',
134    (CHAR) '\240',
135    (CHAR) '\041',
136    (CHAR) '\042',
137    (CHAR) '\243',
138    (CHAR) '\044',
139    (CHAR) '\245',
140    (CHAR) '\246',
141    (CHAR) '\047',
142    (CHAR) '\050',
143    (CHAR) '\251',
144    (CHAR) '\252',
145    (CHAR) '\053',
146    (CHAR) '\254',
147    (CHAR) '\055',
148    (CHAR) '\056',
149    (CHAR) '\257',
150    (CHAR) '\060',
151    (CHAR) '\261',
152    (CHAR) '\262',
153    (CHAR) '\063',
154    (CHAR) '\264',
155    (CHAR) '\065',
156    (CHAR) '\066',
157    (CHAR) '\267',
158    (CHAR) '\270',
159    (CHAR) '\071',
160    (CHAR) '\072',
161    (CHAR) '\273',
162    (CHAR) '\074',
163    (CHAR) '\275',
164    (CHAR) '\276',
165    (CHAR) '\077',
166    (CHAR) '\300',
167    (CHAR) '\101',
168    (CHAR) '\102',
169    (CHAR) '\303',
170    (CHAR) '\104',
171    (CHAR) '\305',
172    (CHAR) '\306',
173    (CHAR) '\107',
174    (CHAR) '\110',
175    (CHAR) '\311',
176    (CHAR) '\312',
177    (CHAR) '\113',
178    (CHAR) '\314',
179    (CHAR) '\115',
180    (CHAR) '\116',
181    (CHAR) '\317',
182    (CHAR) '\120',
183    (CHAR) '\321',
184    (CHAR) '\322',
185    (CHAR) '\123',
186    (CHAR) '\324',
187    (CHAR) '\125',
188    (CHAR) '\126',
189    (CHAR) '\327',
190    (CHAR) '\330',
191    (CHAR) '\131',
192    (CHAR) '\132',
193    (CHAR) '\333',
194    (CHAR) '\134',
195    (CHAR) '\335',
196    (CHAR) '\336',
197    (CHAR) '\137',
198    (CHAR) '\140',
199    (CHAR) '\341',
200    (CHAR) '\342',
201    (CHAR) '\143',
202    (CHAR) '\344',
203    (CHAR) '\145',
204    (CHAR) '\146',
205    (CHAR) '\347',
206    (CHAR) '\350',
207    (CHAR) '\151',
208    (CHAR) '\152',
209    (CHAR) '\353',
210    (CHAR) '\154',
211    (CHAR) '\355',
212    (CHAR) '\356',
213    (CHAR) '\157',
214    (CHAR) '\360',
215    (CHAR) '\161',
216    (CHAR) '\162',
217    (CHAR) '\363',
218    (CHAR) '\164',
219    (CHAR) '\365',
220    (CHAR) '\366',
221    (CHAR) '\167',
222    (CHAR) '\170',
223    (CHAR) '\371',
224    (CHAR) '\372',
225    (CHAR) '\173',
226    (CHAR) '\374',
227    (CHAR) '\175',
228    (CHAR) '\176',
229    (CHAR) '\377'
230};
231
232/* CRC generation tables */
233
234long crcta[16] = { 0L, 010201L, 020402L, 030603L, 041004L,
235  051205L, 061406L, 071607L, 0102010L, 0112211L, 0122412L, 0132613L, 0143014L,
236  0153215L, 0163416L, 0173617L
237};
238
239long crctb[16] = { 0L, 010611L, 021422L, 031233L, 043044L,
240  053655L, 062466L, 072277L, 0106110L, 0116701L, 0127532L, 0137323L, 0145154L,
241  0155745L, 0164576L, 0174367L
242};
243
244#ifdef CK_TIMERS
245/*
246  Round-trip timer calculations adapted from Tim Kientzle's article,
247  "Improving Kermit Performance", Dr Dobb's Journal, February 1996.
248*/
249
250/*  R T T I N I T  --  Initialize timers at start of transaction  */
251
252VOID
253rttinit() {                             /* Initialize round-trip timing */
254    int i;
255
256    rttsamples  = 0L;                   /* Samples (packets) */
257    rttvariance = 0L;                   /* Variance in delay */
258    rttdelay    = (long) timint * RTT_SCALE; /* Delay */
259    pktintvl    = (long) timint * RTT_SCALE; /* Delay */
260    rttstddev   = (long) timint * RTT_SCALE; /* Standard deviation of delay */
261
262    /* Tables of timestamps indexed by packet sequence number */
263
264    for (i = 0; i < 64; i++) {         
265        rrttbl[i] = -1;                 /* Time each packet was received */
266        srttbl[i] = -1;                 /* Time each packet was sent */
267    }
268    rcvtimo = timint;                   /* Initial timeout is what user said */
269}
270
271/*  G E T R T T  --  Get packet round trip time  */
272/*
273  Call with nakstate == 0 if file sender, nonzero if receiver,
274  and n == packet sequence number of the packet we just received.
275 
276  Returns:
277  -1 on failure with rcvtimo set to timint (what the user said), or:
278   0 on success with rcvtimo set to dynamically calculated value:
279     1 <= rcvtimo <= timint * 3.
280*/
281int
282getrtt(nakstate, n) int nakstate, n; {
283    long rttdiff;
284    extern int mintime, maxtime;
285
286    int x, y, yy, z = 0, zz = 0;        /* How long did it take to get here? */
287
288    rcvtimo = timint;                   /* Default timeout is what user said */
289
290    if (timint == 0)                    /* We're not timing out. */
291      return(0);
292
293    if (!rttflg)                        /* Not supposed to be doing this? */
294      return(-1);                       /*  So don't */
295
296    if (!RTT_SCALE)                     /* Paranoia... */
297      return(-1);
298
299    /* rtimer() (reset timer) is not called until 1st data packet */
300    /* S (F [ A ] D* Z)* B */
301
302    /* NOTE: we calculate both the round-trip time AND the packet */
303    /* arrival rate.  We don't use the RTT for anything, we just display it. */
304    /* Timeouts are based on the packet arrival rate. */
305
306    if (spackets > 3) {                 /* Don't start till 4th packet */
307        if (nakstate) {                 /* File receiver */
308            x = rrttbl[n];                   /* Time when I got packet n */
309            y = rrttbl[n > 0 ? n - 1 : 63];  /* Time when I got packet n-1 */
310            yy = srttbl[n > 0 ? n - 1 : 63]; /* Time when I sent ACK(n-1) */
311            if (x > -1 && y > -1) {     /* Be careful */
312                z = x - y;              /* Packet rate */
313                zz = x - yy;            /* Round trip time */
314                debug(F101,"RTT RECV","",z);
315            } else {                    /* This shouldn't happen */
316                debug(F101,"RTT RECV ERROR spackets","",spackets);
317                debug(F101,"RTT RECV ERROR sequence","",n);
318                return(-1);
319            }
320        } else {                        /* File sender */
321            x = rrttbl[n];              /* Time when I got ACK(n) */
322            y = rrttbl[n > 0 ? n - 1 : 63]; /* Time when I got packet n-1 */
323            yy = srttbl[n];             /* Time when I sent n */
324            if (x > -1 && y > -1) {
325                z = x - y;              /* Packet rate */
326                zz = x - yy;            /* Round trip time */
327                debug(F101,"RTT SEND","",z);
328            } else {
329                debug(F100,"RTT SEND ERROR","",0);
330                return(-1);
331            }
332        }
333        if (z < 1)                      /* For fast connections */
334          z = RTT_SCALE / 2;            /* Convert to scale... */
335        else
336          z *= RTT_SCALE;
337
338        if (zz < 1)                     /* For fast connections */
339          zz = RTT_SCALE / 2;           /* Convert to scale... */
340        else
341          zz *= RTT_SCALE;
342
343        rttdelay = zz;                  /* Round trip time of this packet */
344        if (rttsamples++ == 0L) {       /* First sample */
345            pktintvl = z;
346            rttdiff = 0;
347        } else {                        /* Subsequent samples */
348            long oldavg = pktintvl;
349            long rttdiffsq;
350
351            if (rttsamples > 30)        /* Use real average for first 30 */
352              rttsamples = 30;          /*  then decaying average. */
353
354            /* Average delay, difference squared, variance, std deviation */
355
356            pktintvl += (z - pktintvl) / rttsamples;
357            rttdiffsq = (z - oldavg) * (z - oldavg);
358            rttvariance += (rttdiffsq - rttvariance) / rttsamples;
359            debug(F101,"RTT stddev1","",rttstddev);
360            if (rttstddev < 1L)         /* It can be zero, in which case */
361              rttstddev = RTT_SCALE / 3; /* set it to something small... */
362            rttstddev = (rttstddev + rttvariance / rttstddev) / 2;
363        }
364        debug(F101,"RTT stddev2","",rttstddev);
365        debug(F101,"RTT delay  ","",pktintvl);
366        rcvtimo = (pktintvl + (3L * rttstddev)) / RTT_SCALE + 1;
367        if (rpackets < 32)              /* Allow for slow start */
368          rcvtimo += rcvtimo + 2;
369        else if (rpackets < 64)
370          rcvtimo += rcvtimo / 2 + 1;
371        if (rcvtimo < mintime)          /* Lower bound */
372          rcvtimo = mintime;
373        if (maxtime > 0) {              /* User specified an upper bound */
374            if (rcvtimo > maxtime)
375              rcvtimo = maxtime;
376        } else if (maxtime == 0) {      /* User didn't specify */
377            if (rcvtimo > timint * 6)
378              rcvtimo = timint * 6;
379        }
380        debug(F101,"RTT rcvtimo","",rcvtimo);
381    }
382    return(0);
383}
384#endif /* CK_TIMERS */
385
386/*  I N P U T  --  Attempt to read packet number 'pktnum'.  */
387
388/*
389 This is the function that feeds input to Kermit's finite state machine,
390 in the form of a character in the range 32-126, normally a packet type
391 (uppercase letter) or pseudo-packet-type (lowercase letter).
392
393 If a special start state is in effect, that state is returned as if it were
394 the type of an incoming packet.
395*/
396int
397input() {
398    int type, acktype;                  /* Received packet type */
399    int x, y, k;                        /* Workers */
400    int z, pi, nf;                      /* Worker, packet index, NAK flag */
401    int nak2ack = 0;
402
403    debug(F101,"input sstate","",sstate);
404    debug(F101," nakstate","",nakstate);
405    debug(F000," sndtyp","",sndtyp);
406
407    while (1) {                         /* Big loop... */
408
409        if (sstate != 0) {              /* If a start state is in effect, */
410            type = sstate;              /* return it like a packet type, */
411            sstate = 0;                 /* and then nullify it. */
412            numerrs = 0;                /* (PWP) no errors so far */
413            return(type);
414        }
415       
416        if (nakstate) {                 /* This section for file receiver. */
417
418            if (wslots > 1) {           /* If we're doing windows, */
419                x = rseqtbl[winlo];     /* see if desired packet already in. */
420                debug(F101," winlo","",winlo);
421                debug(F101," rseqtbl[winlo]","",rseqtbl[winlo]);
422                if (x > -1) {           /* Already there? */
423                    if (r_pkt[x].pk_seq == winlo) { /* (double check) */
424                        rsn = winlo;                /* Yes, return its info */
425                        debug(F101,"input return pre-stashed packet","",rsn);
426                        dumprbuf();
427                        rdatap = r_pkt[x].pk_adr;   /* like rpack would do. */
428                        rln = (int)strlen((char *) rdatap);
429                        type = r_pkt[x].pk_typ;
430                        break;
431                    }
432                }
433            }
434            type = rpack();             /* Try to read a packet. */
435            debug(F111,"input recv",(char *) rdatap,(int) type);
436            while (type == 'e') {       /* Handle echoes */
437                debug(F000,"echo discarded","",type);
438                type = rpack();
439            }           
440#ifndef OLDCHKINT
441            if (type == 'z') {
442                errpkt((CHAR *)"User cancelled.");
443                strcpy((char *)pktmsg,"User cancelled.");
444                type = 'E';
445                break;
446            }
447#endif /* OLDCHKINT */
448            if (type < -1) return('q'); /* Ctrl-C or connection lost */
449            if (type < 0) {             /* Receive window full */
450                /* Another thing to do here would be to delete */
451                /* the highest packet and NAK winlo.  But that */
452                /* shouldn't be necessary since the other Kermit */
453                /* should not have sent a packet outside the window. */
454                debug(F101,"rpack receive window full","",0);
455                dumprbuf();
456                errpkt((CHAR *)"Receive window full.");
457                strcpy((char *)pktmsg,"Receive window full.");
458                type = 'E';
459                break;
460            }
461            dumprbuf();
462
463#ifdef OLDCHKINT
464            if (chkint() < 0) {         /* Check for console interrupts. */
465                errpkt((CHAR *)"User cancelled.");
466                strcpy((char *)pktmsg,"User cancelled.");
467                type = 'E';
468                break;
469            }
470#endif /* OLDCHKINT */
471
472            if (type == 'E') {
473                debug(F101,"input got E, nakstate","",nakstate);
474                break;                  /* Error packet */
475            }
476            if (type == 'Q') {          /* Crunched packet. */
477                crunched++;
478                numerrs++;
479/*
480  Packet arrived damaged.  It was most likely the packet we were expecting
481  next, so we send a NAK for that packet.  Prior to 5A(189), we always
482  NAK'd winlo here, but that was bad because if two (or more) different
483  packets were damaged, we would keep NAKing the first one and never NAK the
484  other ones, which could result in a lengthy series of timeouts.  Now we
485  NAK the oldest as-yet-unNAK'd missing packet.
486*/
487#ifdef CK_TIMERS
488                rcvtimo++;              /* Stretch the timeout a little */
489#endif /* CK_TIMERS */
490                z = (winlo + wslots) % 64;  /* Search from winlo to z */
491                debug(F101,"ZZZ crunched z","",z);
492                nf = 0;                     /* NAK flag not set yet */
493                for (x = winlo; x != z; x = (x + 1) % 64) {
494                    debug(F101,"ZZZ x","",x);
495                    if (rseqtbl[x] > -1) /* Have I received packet x? */
496                      continue;          /* Yes, go on. */
497                    debug(F101,"ZZZ x not recd yet","",x);
498                    pi = sseqtbl[x];     /* No, have I NAK'd it yet? */
499                    if (pi < 0 || s_pkt[pi].pk_rtr == 0) {
500                        debug(F101,"ZZZ x not NAK'd yet","",x);
501                        nack(x);         /* No, NAK it now. */
502                        nf = 1;          /* Flag that I did. */
503                        break;
504                    }
505                }
506                if (!nf) {              /* If we didn't NAK anything above, */
507                    debug(F101,"ZZZ NAKing winlo","",winlo);
508                    if (nack(winlo) < 0) { /* we have to NAK winlo (again) */
509                        errpkt((CHAR *)"Too many retries."); /* Too many */
510                        strcpy((char *)pktmsg,"Timed out."); /* Give up */
511                        type = 'E';
512                        break;
513                    }
514                }
515                continue;
516            }
517
518            if (type == 'T') {          /* Timeout */
519#ifdef CK_TIMERS
520                rcvtimo++;              /* Stretch the timeout a little */
521#endif /* CK_TIMERS */
522                timeouts++;
523                debug(F101,"input receive-state timeout, winlo","",winlo);
524                /* NAK only the packet at window-low */
525                debug(F101,"input sending NAK for winlo","",winlo);
526                if (ttchk() > 0)        /* Don't give up if there is still */
527                  continue;             /* something to read. */
528                if (nack(winlo) < 0) {
529                    debug(F101,"input sent too many naks","",winlo);
530                    errpkt((CHAR *)"Too many retries.");
531                    strcpy((char *)pktmsg,"Sent too many NAKs.");
532                    type = 'E';
533                    break;
534                } else continue;
535            }
536
537            if (rsn == winlo) {         /* Got the packet we want, done. */
538#ifdef CK_TIMERS
539                if (rttflg)             /* Dynamic round trip timers? */
540                  getrtt(nakstate, rsn); /* yes, do it. */
541#endif /* CK_TIMERS */
542                debug(F101,"input rsn=winlo","",rsn);
543                break;
544            }
545
546            /* Got a packet out of order. */
547
548            debug(F101,"input recv got packet out of order","",rsn);
549            k = rseqtbl[rsn];           /* Get window slot of this packet. */
550            debug(F101,"input recv rseqtbl[rsn]","",k);
551            if (k < 0) {
552                debug(F101,"input recv can't find index for rcvd pkt","",rsn);
553                /* Was "Internal error 21" */
554                errpkt((CHAR *)"Sliding windows protocol error.");
555                strcpy((char *)pktmsg,"Sliding windows protocol error.");
556                type = 'E';
557                break;
558            }           
559            y = chkwin(rsn,winlo,wslots); /* See what window it's in. */
560            debug(F101,"input recv chkwin","",y);
561            if (y == 1) {               /* From previous window. */
562                resend(rsn);            /* Resend the ACK (might have data) */
563                freerpkt(rsn);          /* Get rid of received packet */
564                continue;
565            } else {                    /* In this window or out of range */
566                if (y < 0)              /* If out of range entirely, */
567                  freerpkt(rsn);        /* release its buffer */
568
569#ifdef COMMENT /* Ignore this and read what comes afterwards... */
570/*
571  We have received a packet, but not the one we want.  It would seem to
572  make sense to always send a NAK for the most desired packet (winlo).  But
573  consider this scenario: a packet arrived damaged so we NAK'd it above;
574  then packets winlo+1, winlo+2, ... winlo+n arrive, each one making us
575  send another NAK for winlo, so the other Kermit gets n NAKs for winlo, and
576  either would have to resend it n times, or if n > retry limit, give up
577  because of too many retries.  So we compromise: If a packet arrives
578  that is not the most desired packet (winlo), we NAK winlo, BUT ONLY IF
579  it has not been NAK'd before.
580*/
581                x = sseqtbl[winlo];     /* Get index of most desired packet */
582                if (s_pkt[x].pk_rtr == 0 ||   /* Not NAK'd before? */
583                    rbufnum < 1) {            /* Or receive window full? */
584                    if (nack(winlo) < 0) {    /* One or both, so NAK it now. */
585                        errpkt((CHAR *)"Too many retries."); /* Too many */
586                        strcpy((char *)pktmsg,"Timed out."); /* Give up */
587                        type = 'E';
588                        break;
589                    } else continue;
590                } else continue;
591#endif /* COMMENT */
592
593/*
594  In version 5A(189), the strategy was revised to send NAKs for the oldest
595  missing packet that had not been NAK'd before, which requires a search.
596  Thus, if winlo was already NAK'd, instead of doing nothing, we send a NAK
597  for the "lowest" as-yet-unNAK'd missing packet.
598
599  If our receive window is full, however, we have no choice but to NAK winlo:
600*/
601                debug(F101,"XXX checking rbufnum","",rbufnum);
602                if (rbufnum < 1) {      /* Receive window full? */
603                    debug(F101,"XXX out of buffers","",rbufnum); /* Yes */
604                    if (nack(winlo) < 0) {    /* No choice, must NAK winlo. */
605                        errpkt((CHAR *)"Too many retries."); /* Too many */
606                        strcpy((char *)pktmsg,"Timed out."); /* Give up */
607                        type = 'E';
608                        break;
609                    } else continue;
610                }
611/*
612  Receive window not full.  This is a packet in the current window but it is
613  not the desired packet at winlo.  So therefore there are gaps before this
614  packet.  So we find the "lowest" unNAK'd missing packet, if any, between
615  winlo and this one, and NAK it.  If there are no as-yet-unNAK'd missing
616  packets in the window, then we send nothing and go wait for another packet.
617  In theory, this could result in a timeout, but in practice it is likely that
618  the already-NAK'd missing packets are already on their way.  Note, we do not
619  NAK ahead of ourselves, as that only creates unnecessary retransmissions.
620*/
621                debug(F101,"XXX winlo","",winlo);
622                for (x = winlo; x != rsn; x = (x + 1) % 64) {
623                    debug(F101,"XXX x","",x);
624                    if (rseqtbl[x] > -1) /* Have I received packet x? */
625                      continue;          /* Yes, check next sequence number. */
626                    debug(F101,"XXX missing pkt","",x);
627                    pi = sseqtbl[x];     /* No, have I NAK'd it yet? */
628                    if (pi < 0 || s_pkt[pi].pk_rtr == 0) {
629                        nack(x);         /* No, NAK it now. */
630                        debug(F101,"XXX nak","",x);
631                        break;
632                    }
633                }
634            }
635/*!!!*/
636        } else {                        /* Otherwise file sender... */
637
638            if (!nak2ack) {             /* NAK(n+1) = ACK(n) */
639
640                if (wslots > 1) {       /* Packet at winlo already ACK'd? */
641                    if (sacktbl[winlo]) { /* If so,  */
642                        sacktbl[winlo] = 0; /* Turn off the ACK'd flag */
643                        winlo = (winlo + 1) % 64; /* Rotate the window */
644                        type = 'Y';     /* And return ACK */
645                        debug(F101,
646                              "input send returning pre-stashed ACK","",
647                              winlo-1);
648                        break;
649                    }
650                }
651                type = rpack();         /* Try to read an acknowledgement */
652                debug(F111,"input send",(char *) rdatap,(int) type);
653                while (type == 'e') {   /* Handle echoes */
654                    debug(F000,"echo discarded","",type);
655                    type = rpack();     
656                }               
657#ifndef OLDCHKINT
658                if (type == 'z') {
659                    errpkt((CHAR *)"User cancelled.");
660                    strcpy((char *)pktmsg,"User cancelled.");
661                    type = 'E';
662                    break;
663                }
664#endif /* OLDCHKINT */
665                if (type == -2) return('q');
666                if (type == -1) {
667                    errpkt((CHAR *)"Receive window full"); /* was "internal */
668                    debug(F101," wslots","",wslots); /* error 18" */
669                    debug(F101," winlo","",winlo);
670                    debug(F101," pktnum","",pktnum);
671                    dumprbuf();
672                    strcpy((char *)pktmsg,"Can't allocate receive buffer");
673                    type = 'E';
674                    break;
675                }
676                dumprbuf();             /* Debugging */
677
678#ifdef OLDCHKINT
679                if (chkint() < 0) {     /* Check for console interrupts. */
680                    errpkt((CHAR *)"User cancelled.");
681                    strcpy((char *)pktmsg,"User cancelled.");
682                    return(type = 'E');
683                }
684#endif /* OLDCHKINT */
685
686                /* Got a packet */
687
688                if (type == 'E') {
689                    debug(F101,"input send got E, nakstate","",nakstate);
690                    break;              /* Error packet */
691                }
692                if (type == 'Q') {      /* Crunched packet */
693                    crunched++;         /* For statistics */
694                    numerrs++;          /* For packet resizing */
695                    x = resend(winlo);  /* Resend window-low */
696                    if (x < 0) {
697                        type = 'E';
698                        errpkt(pktmsg);
699                        break;
700                    }
701                    continue;
702                }
703                if (type == 'T') {      /* Timeout waiting for ACKs. */
704                    timeouts++;         /* Count it */
705                    numerrs++;          /* Count an error too */
706                    debug(F101,"input send state timeout, winlo","",winlo);
707
708                    /* Retransmit the oldest un-ACK'd packet. */
709
710                    debug(F101,"input send resending winlo","",winlo);
711                    if (resend(winlo) < 0) { /* Check retries */
712                        debug(F101,"input send too many resends","",maxtry);
713                        errpkt(pktmsg);
714                        return(type = 'E');
715                    }
716#ifdef NEWDPL
717                    /* Reduce prevailing packet length */
718                    x = sseqtbl[winlo]; /* Get length of packet we want ACKd */
719                    if (x > -1) {       /* Only if we have a valid index */
720                        if (s_pkt[x].pk_typ == 'D') { /* only for D packets */
721                            spsiz = (s_pkt[x].pk_len + 8) >> 1; /* halve it */
722                            if (spsiz < 20) spsiz = 20; /* within reason */
723                            debug(F101,"input T cut packet length","",spsiz);
724                        }
725                    }
726#endif /* NEWDPL */
727                    continue;
728                }
729            }
730            /* Got an actual normal packet */
731
732            nak2ack = 0;                /* Unset this flag. */
733            y = chkwin(rsn,winlo,wslots); /* Is it in the window? */
734            debug(F101,"input send rsn","",rsn);
735            debug(F101,"input send winlo","",winlo);
736            debug(F101,"input send chkwin","",y);
737
738            if (type == 'Y') {          /* Got an ACK */
739                if (y == 0) {           /* In current window */
740                    if (spackets < 4)   /* Error counter doesn't count */
741                      numerrs = 0;      /* until data phase. */
742                    sacktbl[rsn]++;     /* Mark the packet as ACK'd */
743                    x = sseqtbl[rsn];   /* Get ACK'd packet's buffer index */
744                    debug(F101,"bestlen ack x","",x);
745#ifdef NEWDPL
746                    if (x > -1) {
747                        acktype = s_pkt[x].pk_typ; /* Get type */
748                        debug(F000,"bestlen ack type","",acktype);
749
750                        if (acktype == 'D') { /* Adjust data packet length */
751                            if (spsiz > bestlen) {
752                                bestlen = spsiz;
753                                debug(F101,"bestlen B","",bestlen);
754                            }
755#ifdef DEBUG                   
756                            if (deblog) {
757                                debug(F101,"bestlen retry","",s_pkt[x].pk_rtr);
758                                debug(F101,"bestlen len","",s_pkt[x].pk_len);
759                                debug(F101,"bestlen spackets","",spackets);
760                            }
761#endif /* DEBUG */
762                            /* Set new best length */
763                            if (s_pkt[x].pk_rtr == 0 &&
764                                s_pkt[x].pk_len + 8 > bestlen) {
765                                bestlen = s_pkt[x].pk_len + 8;
766                                if (bestlen > spmax)
767                                  bestlen = spmax;
768                                debug(F101,"bestlen A","",bestlen);
769                            }
770#ifdef DEBUG                   
771                            if (deblog) {
772                                debug(F101,"bestlen wslots","",wslots);
773                                debug(F101,"bestlen maxsend","",maxsend);
774                            }
775#endif /* DEBUG */
776                            /* Slow start */
777                            if (slostart &&
778                                (maxsend <= spmax) &&
779                                (rpackets < 11) &&
780                                (numerrs == 0)) {
781                                spsiz = spsiz << 1;
782                                debug(F101,"bestlen spsiz A","",spsiz);
783
784                            /* Creep up to best length */
785                            } else if ((spackets > 5) &&
786                                       (spsiz < bestlen - 8)) {
787                                spsiz += (bestlen - spsiz) / 3;
788                                debug(F101,"bestlen spsiz B","",spsiz);
789
790                            /* Push the envelope */
791                            } else if ((spackets % (wslots + 1) == 0) &&
792                                       (spackets > 6) &&
793                                       (bestlen < spmax - 8) &&
794                                       (spsiz < spmax)) {
795                                spsiz += (spmax - bestlen) / 3;
796                                debug(F101,"bestlen spsiz C","",spsiz);
797                            }
798                            /* But not too far */
799                            if (spsiz > spmax) {
800                                spsiz = spmax;
801                                debug(F101,"bestlen spsiz D","",spsiz);
802                            }
803                        }
804                    }
805#endif /* NEWDPL */
806
807#ifdef CK_TIMERS
808                    if (rttflg)         /* If doing dynamic timers */
809                      getrtt(nakstate, rsn); /* call routine to set it. */
810#endif /* CK_TIMERS */
811/*
812  NOTE: The following statement frees the buffer of the ACK we just got.
813  But the upper layers still need the data, like if it's the ACK to an I,
814  S, F, D, Z, or just about any kind of packet.  So for now, freerbuf()
815  deallocates the buffer, but does not erase the data or destroy the pointer
816  to it.  There's no other single place where these receive buffers can be
817  correctly freed (?) ...
818*/
819                    freerpkt(rsn);      /* Free the ACK's buffer */
820                    freesbuf(rsn);      /* *** Free the sent packet's buffer */
821                    if (rsn == winlo) { /* Got the one we want */
822                        sacktbl[winlo] = 0;
823                        winlo = (winlo + 1) % 64;
824                        debug(F101,"input send rotated send window","",winlo);
825                        break;          /* Return the ACK */
826                    } else {
827                        debug(F101,"input send mark pkt","",rsn);
828                        continue;       /* Otherwise go read another packet */
829                    }
830                } else if (y == 1 && wslots < 2) { /* (190) ACK for previous */
831                    numerrs++;          /* == NAK for current, count error */
832                    debug(F101,"input send ACK for previous","",rsn);
833                    freerpkt(rsn);      /* Free NAK's buffer */
834                    x = resend(winlo);  /* Resend current packet */
835                    if (x < 0) {
836                        type = 'E';
837                        errpkt(pktmsg);
838                        break;
839                    } else continue;    /* Resend ok, go read another packet */
840                } else {                /* Other cases, just ignore */
841                    debug(F101,"input send ACK out of window","",rsn);
842                    freerpkt(rsn);
843                    continue;
844                }
845            }
846            if (type == 'N') {          /* NAK */
847                numerrs++;              /* Count an error */
848                debug(F101,"input send NAK","",rsn);
849#ifdef NEWDPL
850                /* Reduce prevailing packet length */
851                x = sseqtbl[rsn];       /* Length of packet that was NAK'd */
852                if (x > -1) {           /* If it's a Data packet we've sent */
853                    if (s_pkt[x].pk_typ == 'D') {
854                        spsiz = (s_pkt[x].pk_len + 8) >> 1; /* Halve length */
855#ifdef COMMENT
856                        /* This might be a good idea -- haven't tried it ... */
857                        if (bestlen > 0 && spsiz > bestlen)
858                          spsiz = bestlen;
859#endif /* COMMENT */
860                        if (spsiz < 20) spsiz = 20;
861                        debug(F101,"input N cut packet length","",spsiz);
862                    }
863                }
864#endif /* NEWDPL */
865                freerpkt(rsn);          /* Free buffer where NAK lies. */
866                if (y == 0) {           /* In current window */         
867                    debug(F100," in window","",0);
868                    k = sseqtbl[rsn];   /* Get pointer to NAK'd packet. */
869                    if (k < 0 || (k > -1 && s_pkt[k].pk_typ == ' ')) {
870                        x = resend(winlo); /* Packet we haven't sent yet. */
871                    } else {
872                        x = resend(rsn); /* Resend requested packet. */
873                    }
874                    if (x < 0) {        /* Resend error is fatal.  */
875                        type = 'E';
876                        errpkt(pktmsg);
877                        break;
878                    } else continue;    /* Resend ok, go read another packet */
879                } else if ((rsn == (pktnum + 1) % 64)) { /* NAK for next pkt */
880                    if (wslots > 1) {
881                        debug( F101,"NAK for next packet, windowing","",rsn);
882                        x = resend(winlo); /* Resend window-low */
883                        if (x < 0) {
884                            type = 'E';
885                            errpkt(pktmsg);
886                            break;
887                        }
888                        continue;       /* Go back and read another pkt */
889                    }
890                    debug(F101,"NAK for next packet, no windowing","",rsn);
891                    x = (rsn == 0) ? 63 : rsn - 1;
892                    if (x == 0 && (sndtyp == 'S' || sndtyp == 'I')) {
893                        resend(0);      /* ACK for S or I packet missing */
894                        continue;       /* so resend the S or I */
895                    }           
896                    rsn = x;            /* Else, treat NAK(n+1) as ACK(n) */
897                    nak2ack = 1;        /* Go back and process the ACK */
898                    continue;
899                } else if (y > 0) {     /* NAK for pkt we can't resend */
900                    debug(F101," NAK out of window","",rsn); /* bad... */
901                    type = 'E';
902                    errpkt((CHAR *)"NAK out of window");
903                    strcpy((char *)pktmsg,"NAK out of window.");
904                    break;
905                } else continue;        /* Ignore other NAKs */
906            }                           /* End of file-sender NAK handler */
907
908            if (rsn == winlo) {         /* Not ACK, NAK, timeout, etc. */
909                debug(F000,"input send unexpected type","",type);
910                break;
911            }
912        }                               /* End of file-sender section */
913    }                                   /* End of input() while() loop */
914    if (wslots == 1) {
915        debug(F100,"input about to flush","",0);
916        ttflui();               /* Got what we want, clear input buffer. */
917    }
918#ifndef NEWDPL
919    if (!nakstate)              /* When sending */
920      rcalcpsz();               /* recalculate size every packet */
921#endif /* NEWDPL */
922    debug(F000,"input returning type","",type);
923    return(rcvtyp = type);      /* Success, return packet type. */
924}
925
926/*  D O P A R  --  Add an appropriate parity bit to a character  */
927
928/*
929  (PWP) this is still used in the Mac terminal emulator, so we have to keep it
930*/
931CHAR
932#ifdef CK_ANSIC
933dopar(register CHAR ch)
934#else
935dopar(ch) register CHAR ch;
936#endif /* CK_ANSIC */
937    {
938    register unsigned int a;
939    if (!parity
940#ifdef TCPSOCKET       
941        || (network &&          /* TELNET BINARY MODE */
942            (ttnproto == NP_TELNET) && (me_binary) )
943#endif /* TCPSOCKET */
944        ) return((CHAR) (ch & 255)); else a = ch & 127;
945    switch (parity) {
946        case 'e':  return(p_tbl[a]);                 /* Even */
947        case 'm':  return((CHAR) (a | 128));         /* Mark */
948        case 'o':  return((CHAR) (p_tbl[a] ^ 128));  /* Odd */
949        case 's':  return((CHAR) a);                 /* Space */
950        default:   return((CHAR) a);                 /* Something illegal */
951    }
952}
953
954#ifdef PARSENSE
955/*  P A R C H K  --  Check if Kermit packet has parity  */
956
957/*
958  Call with s = pointer to packet, start = packet start character, n = length.
959  Returns 0 if packet has no parity, -1 on error, or, if packet has parity:
960    'e' for even, 'o' for odd, 'm' for mark.  Space parity cannot be sensed.
961  So a return value of 0 really means either space or none.
962  Returns -2 if parity has already been checked during this protocol operation.
963*/
964int
965#ifdef CK_ANSIC
966parchk(CHAR *s, CHAR start, int n)
967#else
968parchk(s,start,n) CHAR *s, start; int n;
969#endif /* CK_ANSIC */
970/* parchk */ {
971    CHAR s0, s1, s2, s3;
972
973    debug(F101,"parchk n","",n);
974    debug(F101,"parchk start","",start);
975
976    s0 = s[0] & 0x7f;                   /* Mark field (usually Ctrl-A) */
977
978    if (s0 != start || n < 5) return(-1); /* Not a valid packet */
979
980/* Look at packet control fields, which never have 8th bit set */
981/* First check for no parity, most common case. */
982
983    if (((s[0] | s[1] | s[2] | s[3]) & 0x80) == 0)
984      return(0);                        /* No parity or space parity */
985
986/* Check for mark parity */
987
988    if (((s[0] & s[1] & s[2] & s[3]) & 0x80) == 0x80)
989      return('m');                      /* Mark parity */
990
991/* Packet has some kind of parity */
992/* Make 7-bit copies of control fields */
993
994    s1 = s[1] & 0x7f;                   /* LEN */
995    s2 = s[2] & 0x7f;                   /* SEQ */
996    s3 = s[3] & 0x7f;                   /* TYPE */
997
998/* Check for even parity */
999
1000    if ((s[0] == p_tbl[s0]) &&
1001        (s[1] == p_tbl[s1]) &&
1002        (s[2] == p_tbl[s2]) &&
1003        (s[3] == p_tbl[s3]))
1004      return('e');
1005
1006/* Check for odd parity */
1007
1008    if ((s[0] != p_tbl[s0]) &&
1009        (s[1] != p_tbl[s1]) &&
1010        (s[2] != p_tbl[s2]) &&
1011        (s[3] != p_tbl[s3]))
1012      return('o');
1013
1014/* Otherwise it's probably line noise.  Let checksum calculation catch it. */
1015
1016    return(-1);
1017}
1018#endif /* PARSENSE */
1019
1020/*
1021  Check to make sure timeout intervals are long enough to allow maximum
1022  length packets to get through before the timer goes off.  If not, the
1023  timeout interval is adjusted upwards.
1024
1025  This routine is called at the beginning of a transaction, before we
1026  know anything about the delay characteristics of the line.  It works
1027  only for serial communication devices; it trusts the speed reported by
1028  the operating system.
1029
1030  Call with a timout interval.  Returns it, adjusted if necessary.
1031*/ 
1032int
1033chktimo(timo,flag) int timo, flag; {
1034    long cps, z; int x, y;
1035    debug(F101,"chktimo timo","",timo); /* Timeout before adjustment */
1036    debug(F101,"chktimo flag","",flag);
1037
1038    if (flag)                           /* Don't change timeout if user */
1039      return(timo);                     /* gave SET SEND TIMEOUT command. */
1040    debug(F101,"chktimo spmax","",spmax);
1041    debug(F101,"chktimo urpsiz","",urpsiz);
1042
1043    speed = ttgspd();                   /* Get current speed. */
1044    if (speed > 0L && !network) {
1045        cps = speed / 10L;              /* Convert to chars per second */
1046        if (cps > 0L) {
1047            long plen;                  /* Maximum of send and rcv pkt size */
1048            z = cps * (long) timo;      /* Chars per timeout interval */
1049            z -= z / 10L;               /* Less 10 percent */
1050            plen = spmax;
1051            if (urpsiz > spmax) plen = urpsiz;
1052            debug(F101,"chktimo plen","",plen);
1053            if (z < plen) {             /* Compare with packet size */
1054                x = (int) ((long) plen / cps); /* Adjust if necessary */
1055                y = x / 10;             /* Add 10 percent for safety */
1056                if (y < 2) y = 2;       /* Or 2 seconds, whichever is more */
1057                x += y;
1058                if (x > timo)           /* If this is greater than current */
1059                  timo = x;             /* timeout, change the timeout */
1060                debug(F101,"chktimo new timo","",timo);
1061            }
1062        }
1063    }
1064    return(timo);
1065}
1066
1067/*  S P A C K  --  Construct and send a packet  */
1068
1069/*
1070  spack() sends a packet of the given type, sequence number n, with len data
1071  characters pointed to by d, in either a regular or extended- length packet,
1072  depending on len.  Returns the number of bytes actually sent, or else -1
1073  upon failure.  Uses global npad, padch, mystch, bctu, data.  Leaves packet
1074  fully built and null-terminated for later retransmission by resend().
1075  Updates global sndpktl (send-packet length).
1076
1077  NOTE: The global pointer "data" is assumed to point into the 7th position
1078  of a character array (presumably in packet buffer for the current packet).
1079  It was used by getpkt() to build the packet data field.  spack() fills in
1080  the header to the left of the data pointer (the data pointer is defined
1081  in getsbuf() in ckcfn3.c).  If the address "d" is the same as "data", then
1082  the packet's data field has been built "in place" and need not be copied.
1083*/
1084int
1085#ifdef CK_ANSIC
1086spack(char pkttyp, int n, int len, CHAR *d)
1087#else
1088spack(pkttyp,n,len,d) char pkttyp; int n, len; CHAR *d;
1089#endif /* CK_ANSIC */
1090/* spack */ {
1091    register int i;
1092    int j, k, x, lp, longpkt, copy;
1093
1094#ifdef GETMSEC
1095    long t1, t2;
1096#endif /* GETMSEC */
1097
1098    register CHAR *cp, *mydata;
1099    unsigned crc;
1100
1101    debug(F101,"spack n","",n);
1102    debug(F111,"spack data",data,data);
1103    /* debug(F101,"spack d","",d); */
1104    debug(F101,"spack len","",len);
1105
1106    copy = (d != data);                 /* Flag whether data must be copied  */
1107    longpkt = (len + bctl + 2) > 94;    /* Decide whether it's a long packet */
1108    mydata = data - 7 + (longpkt ? 0 : 3); /* Starting position of header */
1109    debug(F101," mydata","",mydata);
1110
1111    k = sseqtbl[n];                     /* Packet structure info for pkt n */
1112    debug(F101," sseqtbl[n]","",k);
1113    if (k < 0) {
1114        debug(F101,"spack sending packet out of window","",n);
1115    } else {                            /* Record packet info */
1116        s_pkt[k].pk_adr = mydata;       /* Remember address of packet. */
1117        s_pkt[k].pk_seq = n;            /* Record sequence number */
1118        s_pkt[k].pk_typ = pkttyp;       /* Record packet type */
1119    }
1120    spktl = 0;                          /* Initialize length of this packet */
1121    i = 0;                              /* and position in packet. */
1122
1123/* Now fill the packet */
1124
1125    mydata[i++] = mystch;               /* MARK */
1126    lp = i++;                           /* Position of LEN, fill in later */
1127
1128    mydata[i++] = tochar(n);            /* SEQ field */
1129    mydata[i++] = pkttyp;               /* TYPE field */
1130    j = len + bctl;                     /* Length of data + block check */
1131    if (longpkt) {                      /* Long packet? */
1132        int x;                          /* Work around SCO Xenix/286 */
1133        x = j / 95;                     /* compiler bug... */
1134        mydata[lp] = tochar(0);         /* Yes, set LEN to zero */
1135        mydata[i++] = tochar(x);        /* High part */
1136        mydata[i++] = tochar(j % 95);   /* Low part */
1137        mydata[i] = '\0';               /* Header checksum */
1138        mydata[i++] = tochar(chk1(mydata+lp));
1139    } else mydata[lp] = tochar(j+2);    /* Normal LEN */
1140
1141    if (copy)                           /* Data field built in place? */
1142      for ( ; len--; i++) mydata[i] = *d++; /* No, must copy. */
1143    else                                /* Otherwise, */
1144      i += len;                         /* Just skip past data field. */
1145    mydata[i] = '\0';                   /* Null-terminate for checksum calc. */
1146
1147    switch (bctu) {                     /* Block check */
1148        case 1:                         /* 1 = 6-bit chksum */
1149            mydata[i++] = tochar(chk1(mydata+lp));
1150            break;
1151        case 2:                         /* 2 = 12-bit chksum */
1152            j = chk2(mydata+lp);
1153            mydata[i++] = (unsigned)tochar((j >> 6) & 077);
1154            mydata[i++] = (unsigned)tochar(j & 077);
1155            break;
1156        case 3:                         /* 3 = 16-bit CRC */
1157            crc = chk3(mydata+lp,parity);
1158            mydata[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);
1159            mydata[i++] = (unsigned)tochar((crc >> 6) & 077);
1160            mydata[i++] = (unsigned)tochar(crc & 077);
1161            break;
1162        case 4:                         /* 2 = 12-bit chksum, blank-free */
1163            j = chk2(mydata+lp);       
1164            mydata[i++] =
1165              (unsigned)(tochar((unsigned)(((j >> 6) & 077) + 1)));
1166            mydata[i++] = (unsigned)(tochar((unsigned)((j & 077) + 1)));
1167            break;
1168    }
1169    mydata[i++] = seol;                 /* End of line (packet terminator) */
1170#ifdef TCPSOCKET
1171/*
1172  If TELNET connection and packet terminator is carriage return,
1173  we must stuff either LF or NUL, according to SET TELNET NEWLINE-MODE
1174  (tn_nlm), to meet the TELNET specification, unless user said RAW.
1175
1176  If NEWLINE-MODE is set to LF instead of CR, we still send CR-NUL
1177  on a NVT connection and CR on a binary connection.
1178*/
1179    if (seol == CR && network && ttnproto == NP_TELNET) {
1180        switch (me_binary ? tn_b_nlm : tn_nlm) { /* NVT or BINARY */
1181            case TNL_CR:
1182                break;
1183            case TNL_CRNUL:
1184                mydata[i++] = NUL ;
1185                break;
1186            case TNL_CRLF:
1187                mydata[i++] = LF ;
1188                break;
1189            }
1190      }
1191#endif /* TCPSOCKET */
1192    mydata[i] = '\0';                   /* Terminate string */
1193    logpkt('s',n,mydata);               /* Log packet */
1194
1195    /* (PWP) add the parity quickly at the end */
1196    switch (parity) {
1197      case 'e':                         /* Even */
1198        for (cp = &mydata[i-1]; cp >= mydata; cp--)
1199          *cp = p_tbl[*cp];
1200        break;
1201      case 'm':                         /* Mark */
1202        for (cp = &mydata[i-1]; cp >= mydata; cp--)
1203          *cp |= 128;
1204        break;
1205      case 'o':                         /* Odd */
1206        for (cp = &mydata[i-1]; cp >= mydata; cp--)
1207          *cp = p_tbl[*cp] ^ 128;
1208        break;
1209      case 's':                         /* Space */
1210        for (cp = &mydata[i-1]; cp >= mydata; cp--)
1211          *cp &= 127;
1212        break;
1213    }
1214    if (pktpaus) msleep(pktpaus);       /* Pause if requested */
1215    if (npad) ttol(padbuf,npad);        /* Send any padding */
1216#ifdef CK_TIMERS
1217    if (pkttyp == 'N')
1218      srttbl[n > 0 ? n-1 : 63] = gtimer();
1219    else
1220      srttbl[n] = gtimer();
1221#endif /* CK_TIMERS */
1222    spktl = i;                          /* Remember packet length */
1223    if (k > -1)
1224      s_pkt[k].pk_len = spktl;          /* also in packet info structure */
1225
1226#ifdef GETMSEC
1227    if (deblog) t1 = getmsec();
1228#endif /* GETMSEC */
1229
1230    x = ttol(mydata,spktl);
1231    if (spktl > maxsend) maxsend = spktl;
1232
1233#ifdef GETMSEC
1234    if (deblog)  {
1235        t2 = getmsec();
1236        if (t2 > -1L && t1 > -1L)
1237          debug(F101,"spack ttol time","",t2-t1);
1238        else
1239          debug(F100,"spack ttol time error","",0);
1240    }
1241#endif /* GETMSEC */
1242
1243    debug(F101,"spack ttol returns","",x);
1244    if (x < 0)
1245      return(x);
1246    sndtyp = pkttyp;                    /* Remember packet type for echos */
1247    spackets++;                         /* Count it. */
1248    flco += spktl;                      /* Count the characters */
1249    tlco += spktl;                      /* for statistics... */
1250    dumpsbuf();                         /* Dump send buffers to debug log */
1251    debug(F100,"spack about to call screen","",0);
1252    debug(F111," with mydata=",mydata,n);
1253    screen(SCR_PT,pkttyp,(long)n,(char *)mydata); /* Update screen */
1254    return(spktl);                      /* Return length */
1255}
1256
1257/*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */
1258
1259int
1260chk1(pkt) register CHAR *pkt; {
1261    register unsigned int chk;
1262    chk = chk2(pkt);
1263    chk = (((chk & 0300) >> 6) + chk) & 077;
1264    return((int) chk);
1265}
1266
1267/*  C H K 2  --  Compute the numeric sum of all the bytes in the packet.  */
1268
1269unsigned int
1270chk2(pkt) register CHAR *pkt; {
1271    register long chk; register unsigned int m;
1272    m = (parity) ? 0177 : 0377;
1273    for (chk = 0; *pkt != '\0'; pkt++)
1274      chk += *pkt & m;
1275    return((unsigned int) (chk & 07777));
1276}
1277
1278
1279/*  C H K 3  --  Compute a type-3 Kermit block check.  */
1280/*
1281 Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup
1282 table.  Assumes the argument string contains no embedded nulls.
1283*/
1284unsigned int
1285chk3(pkt,parity) register CHAR *pkt; int parity; {
1286    register long c, crc;
1287    register unsigned int m;
1288    m = (parity) ? 0177 : 0377;
1289    for (crc = 0; *pkt != '\0'; pkt++) {
1290        c = crc ^ (long)(*pkt & m);
1291        crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);
1292    }
1293    return((unsigned int) (crc & 0xFFFF));
1294}
1295
1296int
1297nxtpkt() {                              /* Called by file sender */
1298    int j, n;
1299
1300    debug(F101,"nxtpkt pktnum","",pktnum);
1301    debug(F101,"nxtpkt winlo ","",winlo);
1302    n = (pktnum + 1) % 64;              /* Increment packet number mod 64 */
1303#ifdef COMMENT
1304/*
1305  Suggested by Alan Grieg.  A packet can be sent out of window in
1306  circumstances involving acks received out of order, ...  Have to think
1307  about this...
1308*/
1309    if (chkwin(n,winlo,wslots)) {
1310        debug(F101,"nxtpkt n not in window","",n);
1311        return(-1);
1312    }
1313#endif
1314    j = getsbuf(n);                     /* Get a buffer for packet n */
1315    if (j < 0) {
1316        debug(F101,"nxtpkt can't getsbuf","",j);
1317        return(-1);
1318    }
1319    pktnum = n;       
1320    debug(F101,"nxtpkt bumped pktnum to","",pktnum);
1321    return(0);
1322}
1323
1324/* Functions for sending ACKs and NAKs */
1325
1326/* Note, we should only ACK the packet at window-low (winlo) */
1327/* However, if an old packet arrives again (e.g. because the ACK we sent */
1328/* earlier was lost), we ACK it again. */
1329
1330int
1331ack() {                                 /* Acknowledge the current packet. */
1332    return(ackns(winlo,(CHAR *)""));
1333}
1334
1335int
1336ackns(n,s) int n; CHAR *s; {            /* Acknowledge packet n */
1337    int j, k;
1338    debug(F111,"ackns",s,n);
1339
1340    k = rseqtbl[n];                     /* First find received packet n. */
1341    debug(F101,"ackns k","",k);
1342    freesbuf(n);                        /* Free current send-buffer, if any */
1343    if ((j = getsbuf(n)) < 0) {
1344        /* This can happen if we have to re-ACK an old packet that has */
1345        /* already left the window.  It does no harm. */
1346        debug(F101,"ackns can't getsbuf","",n);
1347    }
1348    spack('Y',n,(int)strlen((char *)s),s); /* Now send it. */
1349    debug(F101,"ackns winlo","",winlo);
1350    debug(F101,"ackns n","",n);
1351    if (n == winlo) {                   /* If we're acking winlo */
1352        if (k > -1)
1353          freerbuf(k);                  /* don't need it any more */
1354        if (j > -1)
1355          freesbuf(j);                  /* and don't need to keep ACK either */
1356        winlo = (winlo + 1) % 64;
1357    }
1358    return(0);
1359}
1360
1361int
1362ackn(n) int n; {                        /* Send ACK for packet number n */
1363    return(ackns(n,(CHAR *)""));
1364}
1365
1366int
1367ack1(s) CHAR *s; {                      /* Send an ACK with data. */
1368    debug(F110,"ack1",(char *) s,0);
1369    return(ackns(winlo, s));
1370}
1371
1372/* N A C K  --   Send a Negative ACKnowledgment. */
1373/*
1374 Call with the packet number, n, to be NAK'd.
1375 Returns -1 if that packet has been NAK'd too many times, otherwise 0.
1376 Btw, it is not right to return 0 under error conditions.  This is
1377 done because the -1 code is used for cancelling the file transfer.
1378 More work is needed here.
1379*/
1380int
1381nack(n) int n; {
1382    int i;
1383
1384    if (n < 0 || n > 63) {
1385        debug(F101,"nack bad pkt num","",n);
1386        return(0);
1387    } else debug(F101,"nack","",n);
1388    if ((i = sseqtbl[n]) < 0) {         /* If necessary */
1389        if (getsbuf(n) < 0) {           /* get a buffer for this NAK */
1390            debug(F101,"nack can't getsbuf","",n);
1391            return(0);
1392        } else i = sseqtbl[n];          /* New slot number */
1393    }
1394    if (s_pkt[i].pk_rtr++ > maxtry)     /* How many times have we done this? */
1395      return(-1);                       /* Too many... */
1396
1397/* Note, don't free this buffer.  Eventually an ACK will come, and that */
1398/* will set it free.  If not, well, it's back to ground zero anyway...  */
1399
1400    spack('N',n,0,(CHAR *) "");         /* NAKs never have data. */
1401    return(0);
1402}
1403
1404#ifndef NEWDPL                          /* This routine no longer used */
1405/*
1406 * (PWP) recalculate the optimal packet length in the face of errors.
1407 * This is a modified version of the algorithm by John Chandler in Kermit/370,
1408 * see "Dynamic Packet Size Control", Kermit News, V2 #1, June 1988.
1409 *
1410 * This implementation minimizes the total overhead equation, which is
1411 *
1412 *   Total chars = file_chars + (header_len * num_packs)
1413 *                            + (errors * (header_len + packet_len))
1414 *
1415 * Differentiate with respect to number of chars, solve for packet_len, get:
1416 *
1417 *   packet_len = sqrt (file_chars * header_len / errors)
1418 */
1419
1420/*
1421 (FDC) New super-simple algorithm.  If there was an error in the most recent
1422 packet exchange, cut the send-packet size in half, down to a minimum of 20.
1423 If there was no error, increase the size by 5/4, up to the maximum negotiated
1424 length.  Seems to be much more responsive than previous algorithm, which took
1425 forever to recover the original packet length, and it also went crazy under
1426 certain conditions.
1427
1428 Here's another idea for packet length resizing that keeps a history of the
1429 last n packets.  Push a 1 into the left end of an n-bit shift register if the
1430 current packet is good, otherwise push a zero.  The current n-bit value, w, of
1431 this register is a weighted sum of the noise hits for the last n packets, with
1432 the most recent weighing the most.  The current packet length is some function
1433 of w and the negotiated packet length, like:
1434
1435   (2^n - w) / (2^n) * (negotiated length)
1436
1437 If the present resizing method causes problems, think about this one a little
1438 more.
1439*/
1440VOID
1441rcalcpsz() {
1442
1443#ifdef COMMENT
1444/* Old way */
1445    register long x, q;
1446    if (numerrs == 0) return;           /* bounds check just in case */
1447
1448    /* overhead on a data packet is npad+5+bctr, plus 3 if extended packet */
1449    /* an ACK is 5+bctr */
1450
1451    /* first set x = per packet overhead */
1452    if (wslots > 1)                     /* Sliding windows */
1453      x = (long) (npad+5+bctr);         /* packet only, don't count ack */
1454    else                                /* Stop-n-wait */
1455      x = (long) (npad+5+3+bctr+5+bctr); /* count packet and ack. */
1456
1457    /* then set x = packet length ** 2 */
1458    x = x * ( ffc / (long) numerrs);    /* careful of overflow */
1459   
1460    /* calculate the long integer sqrt(x) quickly */
1461    q = 500;
1462    q = (q + x/q) >> 1;
1463    q = (q + x/q) >> 1;
1464    q = (q + x/q) >> 1;
1465    q = (q + x/q) >> 1;         /* should converge in about 4 steps */
1466    if ((q > 94) && (q < 130))  /* break-even point for long packets */
1467      q = 94;
1468    if (q > spmax) q = spmax;   /* maximum bounds */
1469    if (q < 10) q = 10;         /* minimum bounds */
1470    spsiz = q;                  /* set new send packet size */
1471    debug(F101,"rcalcpsiz","",q);
1472#else
1473/* New way */
1474    debug(F101,"rcalcpsiz numerrs","",numerrs);
1475    debug(F101,"rcalcpsiz spsiz","",spsiz);
1476    if (spackets < 3) {
1477        numerrs = 0;
1478        return;
1479    }
1480    if (numerrs)
1481      spsiz = spsiz / 2;
1482    else
1483      spsiz = (spsiz / 4) * 5;
1484    if (spsiz < 20) spsiz = 20;
1485    if (spsiz > spmax) spsiz = spmax;
1486    debug(F101,"rcalcpsiz new spsiz","",spsiz);
1487    numerrs = 0;
1488#endif /* COMMENT */
1489}
1490#endif /* NEWDPL */
1491
1492/*  R E S E N D  --  Retransmit packet n.  */
1493
1494/*
1495  Returns 0 or positive on success (the number of retries for packet n).
1496  On failure, returns a negative number, and an error message is placed
1497  in recpkt.
1498*/
1499int
1500resend(n) int n; {                      /* Send packet n again. */
1501    int j, k, x;
1502#ifdef GETMSEC
1503    long t1, t2;
1504#endif /* GETMSEC */
1505
1506    debug(F101,"resend seq","",n);
1507
1508    k = chkwin(n,winlo,wslots);         /* See if packet in current window */
1509    j = -1;                             /* Assume it's lost */
1510    if (k == 0) j = sseqtbl[n];         /* See if we still have a copy of it */
1511    if (k != 0 || j < 0) {              /* If not.... */
1512        if (nakstate && k == 1) {
1513/*
1514  Packet n is in the previous window and we are the file receiver.
1515  We already sent the ACK and deallocated its buffer so we can't just
1516  retransmit the ACK.  Rather than give up, we try some tricks...
1517*/
1518            if (n == 0 && spackets < 63 && myinit[0]) { /* ACK to Send-Init */
1519/*
1520  If the packet number is 0, and we're at the beginning of a protocol
1521  operation (spackets < 63), then we have to resend the ACK to an I or S
1522  packet, complete with parameters in the data field.  So we take a chance and
1523  send a copy of the parameters in an ACK packet with block check type 1.
1524*/
1525                int bctlsav;            /* Temporary storage */
1526                int bctusav;
1527                bctlsav = bctl;         /* Save current block check length */
1528                bctusav = bctu;         /* and type */
1529                bctu = bctl = 1;        /* Set block check to 1 */
1530                spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);
1531                logpkt('#',n,(CHAR *)"<reconstructed>"); /* Log it */
1532                bctu = bctusav;         /* Restore block check type */
1533                bctl = bctlsav;         /* and length */
1534
1535            } else {                    /* Not the first packet */
1536/*
1537  It's not the first packet of the protocol operation.  It's some other packet
1538  that we have already ACK'd and forgotten about.  So we take a chance and
1539  send an empty ACK using the current block-check type.  Usually this will
1540  work out OK (like when acking Data packets), and no great harm will be done
1541  if it was some other kind of packet (F, etc).  If we are requesting an
1542  interruption of the file transfer, the flags are still set, so we'll catch
1543  up on the next packet.
1544*/
1545                spack('Y',n,0,(CHAR *) "");
1546            }
1547            retrans++;
1548            screen(SCR_PT,'%',(long)pktnum,"Retransmission");
1549            return(0);
1550        } else {
1551/*
1552  Packet number is not in current or previous window.  We seem to hit this
1553  code occasionally at the beginning of a transaction, for apparently no good
1554  reason.  Let's just log it for debugging, send nothing, and try to proceed
1555  with the protocol rather than killing it.
1556*/
1557            debug(F101,"RESEND PKT NOT IN WINDOW","",n);
1558            debug(F101,"RESEND k","",k);
1559#ifdef COMMENT
1560            sprintf((char *)pktmsg,
1561                    "   resend error: NIW, n=%d, k=%d.",n,k);
1562            return(-2);
1563#else
1564            return(0);
1565#endif /* COMMENT */
1566        }
1567    }
1568
1569/* OK, it's in the window and it's not lost. */
1570
1571    debug(F101,"resend pktinfo index","",k);
1572
1573    if (s_pkt[j].pk_rtr++ > maxtry) {   /* Found it but over retry limit */
1574        strcpy((char *)pktmsg,"Too many retries.");
1575        return(-1);
1576    }
1577    debug(F101," retry","",s_pkt[j].pk_rtr); /* OK so far */
1578    dumpsbuf();                         /* (debugging) */
1579    if (s_pkt[j].pk_typ == ' ') {       /* Incompletely formed packet */
1580        if (nakstate) {                 /* (This shouldn't happen any more) */
1581            nack(n);
1582            retrans++;
1583            screen(SCR_PT,'%',(long)pktnum,"(resend)");
1584            return(s_pkt[j].pk_rtr);
1585        } else {                        /* No packet to resend! */
1586#ifdef COMMENT
1587/*
1588  This happened (once) while sending a file with 2 window slots and typing
1589  X to the sender to cancel the file.  But since we're cancelling anyway,
1590  there's no need to give a scary message.
1591*/
1592            sprintf((char *)pktmsg,
1593                    "resend logic error: NPS, n=%d, j=%d.",n,j);
1594            return(-2);
1595#else
1596/* Just ignore it. */
1597            return(0);
1598#endif /* COMMENT */
1599        }
1600    }
1601#ifdef GETMSEC
1602    if (deblog) t1 = getmsec();
1603#endif /* GETMSEC */
1604
1605    /* Everything ok, send the packet */
1606#ifdef CK_TIMERS
1607    srttbl[n] = gtimer();               /* Update the timer */
1608#endif /* CK_TIMERS */
1609    x = ttol(s_pkt[j].pk_adr,s_pkt[j].pk_len);
1610
1611#ifdef GETMSEC
1612    if (deblog)  {
1613        t2 = getmsec();
1614        if (t2 > -1L && t1 > -1L)
1615          debug(F101,"resend ttol time","",t2-t1);
1616        else
1617          debug(F100,"resend ttol time error","",0);
1618    }
1619#endif /* GETMSEC */
1620    debug(F101,"resend ttol returns","",x);
1621
1622    retrans++;                          /* Count a retransmission */
1623    screen(SCR_PT,'%',(long)pktnum,"(resend)"); /* Tell user about resend */
1624    logpkt('S',n,s_pkt[j].pk_adr);      /* Log the resent packet */
1625    return(s_pkt[j].pk_rtr);            /* Return the number of retries. */
1626}
1627
1628int
1629errpkt(reason) CHAR *reason; {          /* Send an error packet. */
1630    int x, y;
1631    encstr(reason);
1632    y = spack('E',pktnum,size,data);
1633    x = quiet; quiet = 1;               /* Close files silently. */
1634    clsif(); clsof(1);
1635    quiet = x;
1636#ifdef COMMENT
1637    screen(SCR_TC,0,0l,"");
1638#endif /* COMMENT */
1639    if (what < W_CONNECT)
1640      xitsta |= what;                   /* Remember what failed. */
1641    success = 0;
1642    return(y);
1643}
1644
1645/* scmd()  --  Send a packet of the given type */
1646
1647int
1648#ifdef CK_ANSIC
1649scmd(char t, CHAR *dat)
1650#else
1651scmd(t,dat) char t; CHAR *dat;
1652#endif /* CK_ANSIC */
1653/* scmd */ {
1654    if (encstr(dat) < 0)                /* Encode the command string */
1655      return(-1);
1656    spack(t,pktnum,size,data);
1657    return(0);
1658}
1659
1660int
1661srinit(reget, retrieve) int reget, retrieve; { /* Send R, H, or J packet */
1662    if (encstr((CHAR *)cmarg) < 0)      /* Encode the filename. */
1663      return(-1);
1664    if (retrieve)
1665      spack((char)'H',pktnum,size,data); /* Send the packet. */
1666    else
1667      spack((char)(reget ? 'J' : 'R'),pktnum,size,data); /* Send the packet. */
1668    return(0);
1669}
1670
1671/*  K S T A R T  --  Checks for a Kermit packet while in terminal mode.  */
1672
1673#ifdef CK_APC
1674int
1675#ifdef CK_ANSIC
1676kstart(CHAR ch)
1677#else
1678kstart(ch) CHAR ch;
1679#endif /* CK_ANSIC */
1680/* kstart */ {
1681    static int buflen = 94;
1682    static CHAR buf[95];
1683    static CHAR * p = NULL;
1684    extern CHAR stchr, eol;
1685
1686    if (ch == stchr) {                  /* Start of packet */
1687        p = buf;
1688        *p = ch;
1689        debug(F101,"kstart SOP","",ch);
1690    } else if (ch == eol) {             /* End of packet */
1691        if (p) {
1692            p++;
1693            if (p - buf < 94 ) {
1694                int rc = 0;
1695                *p = ch;
1696                p++;
1697                *p = NUL;
1698                if (rc = chkspkt((char *)buf))
1699                  debug(F111,"kstart EOP", buf, ch);
1700                p = NULL;
1701                if (!rc) return(0);
1702                return(rc == 1 ? PROTO_K + 1 : 0 - (PROTO_K + 1));
1703            } else {
1704                p = NULL;
1705            }
1706        }
1707    } else if (p) {
1708        p++;
1709        if (p - buf < 94)
1710          *p = ch;
1711        else
1712          p = NULL;
1713    }
1714    return(0);
1715}
1716
1717#ifdef CK_XYZ
1718
1719/*  Z S T A R T  --  Checks for a ZMODEM packet while in terminal mode.  */
1720
1721int
1722#ifdef CK_ANSIC
1723zstart(CHAR ch)
1724#else
1725zstart(ch) CHAR ch;
1726#endif /* CK_ANSIC */
1727/* zstart */ {
1728    static CHAR * matchstr = (CHAR *) "\030B00";
1729    /* "rz\r**\030B00000000000000\r\033J\021"; */
1730    static CHAR * p = NULL;
1731
1732    if (!ch)
1733      return(0);
1734    if (!p)
1735      p = matchstr;
1736
1737    if (ch == *p) {
1738        p++;
1739        if (*p == '\0') {
1740            p = matchstr;
1741            debug(F100, "zstart Zmodem SOP","",0);
1742            return(PROTO_Z + 1);
1743        }
1744    } else
1745      p = matchstr;
1746    return(0);
1747}
1748#endif /* CK_XYZ */
1749
1750/*  C H K S P K T  --  Check if buf contains a valid S or I packet  */
1751
1752int
1753chkspkt(buf) char *buf; {
1754    int buflen;
1755    int len = -1;
1756    CHAR chk;
1757    char type = 0;
1758    char *s = buf;
1759
1760    if (!buf) return(0);
1761    buflen = strlen(buf);
1762    if (buflen < 5) return(0);          /* Too short */
1763    if (*s++ != stchr) return(0);       /* SOH */
1764    len = xunchar(*s++);                /* Length */
1765    if (len < 0) return(0);
1766    if (*s++ != SP) return(0);          /* Sequence number */
1767    type = *s++;                        /* Type */
1768    if (type != 'S' && type != 'I')
1769      return(0);
1770    if (buflen < len + 2) return(0);
1771    s += (len - 3);                     /* Position of checksum */
1772    chk = (CHAR) (*s);                  /* Checksum */
1773    *s = NUL;
1774    if (xunchar(chk) != chk1((CHAR *) (buf+1))) return(0); /* Check it */
1775    *s = chk;
1776    return(type == 'S' ? 1 : 2);
1777}
1778#endif /* CK_APC */
1779
1780/* R P A C K  --  Read a Packet */
1781
1782/*
1783 rpack reads a packet and returns the packet type, or else Q if the
1784 packet was invalid, or T if a timeout occurred.  Upon successful return, sets
1785 the values of global rsn (received sequence number),  rln (received
1786 data length), and rdatap (pointer to null-terminated data field), and
1787 returns the packet type.
1788*/
1789int
1790rpack() {
1791    register int i, j, x, lp;           /* Local variables */
1792    int k, type, chklen;
1793    unsigned crc;
1794    CHAR pbc[4];                        /* Packet block check */
1795    CHAR *sohp;                         /* Pointer to SOH */
1796    CHAR e;                             /* Packet end character */
1797
1798#ifdef GETMSEC
1799    long t1, t2;
1800#endif /* GETMSEC */
1801
1802    debug(F101,"entering rpack, pktnum","",pktnum);
1803
1804#ifndef OLDCHKINT
1805    if (chkint() < 0)                   /* Check for console interrupts. */
1806      return('z');
1807#endif /* OLDCHKINT */
1808
1809    k = getrbuf();                      /* Get a new packet input buffer. */
1810    debug(F101,"rpack getrbuf","",k);
1811    if (k < 0) return(-1);              /* Return like this if none free. */
1812    if (pktmsg) *pktmsg = NUL;
1813    recpkt = r_pkt[k].bf_adr;
1814    *recpkt = '\0';                     /* Clear receive buffer. */
1815    sohp = recpkt;                      /* Initialize pointers to it. */
1816    rdatap = recpkt;
1817    rsn = rln = -1;                     /* In case of failure. */
1818    e = (turn) ? turnch : eol;          /* Use any handshake char for eol */
1819
1820/* Try to get a "line". */
1821
1822#ifdef GETMSEC
1823    if (deblog) t1 = getmsec();
1824#endif /* GETMSEC */
1825
1826#ifdef PARSENSE
1827#ifdef UNIX
1828/*
1829  So far the final turn argument is only for ck[uvdl]tio.c.  Should be added
1830  to the others too.  (turn == handshake character.)
1831*/
1832    j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
1833#else
1834#ifdef VMS
1835    j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
1836#else
1837#ifdef datageneral
1838    j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
1839#else
1840#ifdef STRATUS
1841    j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
1842#else
1843#ifdef OS2
1844    j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
1845#else
1846#ifdef OSK
1847    j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
1848#else
1849    j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr);
1850#endif /* OSK */
1851#endif /* OS2 */
1852#endif /* STRATUS */
1853#endif /* datageneral */
1854#endif /* VMS */
1855#endif /* UNIX */
1856    if (parity != ttprty) autopar = 1;
1857    parity = ttprty;
1858#else /* !PARSENSE */
1859    j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e);
1860#endif /* PARSENSE */
1861
1862#ifdef GETMSEC
1863    if (deblog)  {
1864        t2 = getmsec();
1865        if (t2 > -1L && t1 > -1L)
1866          debug(F101,"rpack ttinl time","",t2-t1);
1867        else
1868          debug(F100,"rpack ttinl time error","",0);
1869    }
1870#endif /* GETMSEC */
1871
1872    if (j < 0) {
1873        debug(F101,"rpack: ttinl fails","",j); /* Otherwise, */
1874        freerbuf(k);                    /* Free this buffer */
1875        if (j < -1) {                   /* Bail out if ^C^C typed. */
1876            debug(F101,"rpack ^C server","",server);
1877            debug(F101,"rpack ^C en_fin","",en_fin);
1878            if (server == 0) return(j); /* But not if in server mode */
1879            else if (en_fin) return(j); /* with DISABLE FINISH */
1880            else return(-2);
1881        }
1882        if (nakstate)                   /* Call it a timeout. */
1883          screen(SCR_PT,'T',(long)winlo,"");
1884        else
1885          screen(SCR_PT,'T',(long)pktnum,"");
1886        logpkt('r',-1,(CHAR *)"<timeout>");
1887        if (flow == 1) ttoc(XON);       /* In case of Xoff blockage. */
1888        return('T');
1889    }
1890    rpktl = j;
1891    tlci += j;                          /* All OK, Count the characters. */
1892    flci += j;
1893
1894#ifndef PARSENSE
1895/* THEN eliminate this loop... */
1896    for (i = 0; (recpkt[i] != stchr) && (i < j); i++)
1897      sohp++;                           /* Find mark */
1898    if (i++ >= j) {                     /* Didn't find it. */
1899        logpkt('r',-1,"<timeout>");
1900        freerbuf(k);
1901        return('T');
1902    }   
1903#else
1904    i = 1;
1905#endif /* PARSENSE */
1906
1907    rpackets++;
1908    lp = i;                             /* Remember LEN position. */
1909    if ((j = xunchar(recpkt[i++])) == 0) {
1910        if ((j = lp+5) > MAXRP) return('Q'); /* Long packet */
1911        x = recpkt[j];                  /* Header checksum. */
1912        recpkt[j] = '\0';               /* Calculate & compare. */
1913        if (xunchar(x) != chk1(recpkt+lp)) {
1914            freerbuf(k);
1915            logpkt('r',-1,(CHAR *)"<crunched:hdr>");
1916            screen(SCR_PT,'%',(long)pktnum,"Bad packet header");
1917            return('Q');
1918        }
1919        recpkt[j] = x;                  /* Checksum ok, put it back. */
1920        rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctl;
1921        j = 3;                          /* Data offset. */
1922    } else if (j < 3) {
1923        debug(F101,"rpack packet length less than 3","",j);
1924        freerbuf(k);
1925        logpkt('r',-1,(CHAR *)"<crunched:len>");
1926        screen(SCR_PT,'%',(long)pktnum,"Bad packet length");
1927        return('Q');
1928    } else {
1929        rln = j - bctl - 2;             /* Regular packet */
1930        j = 0;                          /* No extended header */
1931    }
1932    rsn = xunchar(recpkt[i++]);         /* Sequence number */
1933    logpkt('r',rsn,sohp);
1934    if (rsn < 0 || rsn > 63) {
1935        debug(F101,"rpack bad sequence number","",rsn);
1936        freerbuf(k);
1937        logpkt('r',rsn,(CHAR *)"<crunched:seq>");
1938        screen(SCR_PT,'%',(long)pktnum,"Bad sequence number");
1939        return('Q');
1940    }
1941/*
1942  If this packet has the same type as the packet just sent, assume it is
1943  an echo and ignore it.  Don't even bother with the block check calculation:
1944  even if the packet is corrupted, we don't want to NAK an echoed packet.
1945  (And we certainly don't want to NAK an ACK or NAK!)
1946*/
1947    type = recpkt[i++];                 /* Get packet's TYPE field */
1948    if (type == sndtyp || (nakstate && (type == 'N' /* || type == 'Y' */ ))) {
1949        debug(F000,"rpack echo","",type); /* If it's an echo */
1950        freerbuf(k);                    /* Free this buffer */
1951        logpkt('#',rsn,(CHAR *)"<echo:ignored>");
1952        return('e');                    /* return special (lowercase) code */
1953    }
1954/*
1955  Separate the data from the block check, accounting for the case where   
1956  a packet was retransmitted after the block check switched.
1957*/
1958    if (type == 'I' || type == 'S') {   /* I & S packets always have type 1 */
1959        chklen = 1;
1960        rln = rln + bctl - 1;
1961    } else if (type == 'N') {           /* A NAK packet never has data */
1962        chklen = xunchar(recpkt[lp]) - 2;
1963        rln = rln + bctl - chklen;
1964    } else chklen = bctl;
1965    debug(F101,"rpack bctl","",bctl);
1966    debug(F101,"rpack chklen","",chklen);
1967
1968    i += j;                             /* Buffer index of DATA field */
1969    rdatap = recpkt+i;                  /* Pointer to DATA field */
1970    if ((j = rln + i) > r_pkt[k].bf_len ) { /* Make sure it fits */
1971        debug(F101,"packet sticks out too far","",j);
1972        freerbuf(k);
1973        logpkt('r',rsn,(CHAR *)"<overflow>");
1974        return('Q');
1975    }
1976
1977    for (x = 0; x < chklen; x++)        /* Copy the block check */
1978      pbc[x] = recpkt[j+x];
1979    pbc[x] = '\0';                      /* Null-terminate block check string */
1980    recpkt[j] = '\0';                   /*  and the packet DATA field. */
1981   
1982    if (chklen == 2 && bctu == 4) {     /* Adjust for Blank-Free-2 */
1983        chklen = 4;                     /* (chklen is now a misnomer...) */
1984        debug(F100,"rpack block check B","",0);
1985    }
1986    switch (chklen) {                   /* Check the block check */
1987        case 1:                         /* Type 1, 6-bit checksum */
1988            if (xunchar(*pbc) != chk1(recpkt+lp)) {
1989                debug(F110,"checked chars",recpkt+lp,0);
1990                debug(F101,"block check","",(int) xunchar(*pbc));
1991                debug(F101,"should be","",chk1(recpkt+lp));
1992                freerbuf(k);
1993                logpkt('r',-1,(CHAR *)"<crunched:chk1>");
1994                screen(SCR_PT,'%',(long)pktnum,"Checksum error");
1995                return('Q');
1996            }
1997            break;
1998        case 2:                         /* Type 2, 12-bit checksum */
1999            x = xunchar(*pbc) << 6 | xunchar(pbc[1]);
2000            if (x != chk2(recpkt+lp)) { /* No match */
2001                if (type == 'E') {      /* Allow E packets to have type 1 */
2002                    recpkt[j++] = pbc[0];   
2003                    recpkt[j] = '\0';
2004                    if (xunchar(pbc[1]) == chk1(recpkt+lp))
2005                      break;
2006                    else
2007                      recpkt[--j] = '\0';
2008                }
2009                debug(F110,"checked chars",recpkt+lp,0);
2010                debug(F101,"block check","", x);
2011                debug(F101,"should be","", (int) chk2(recpkt+lp));
2012                freerbuf(k);
2013                logpkt('r',-1,(CHAR *)"<crunched:chk2>");
2014                screen(SCR_PT,'%',(long)pktnum,"Checksum error");
2015                return('Q');
2016            }
2017            break;
2018        case 3:                         /* Type 3, 16-bit CRC */
2019            crc = (xunchar(pbc[0]) << 12)
2020                | (xunchar(pbc[1]) << 6)
2021                | (xunchar(pbc[2]));
2022            if (crc != chk3(recpkt+lp,parity)) {
2023                if (type == 'E') {      /* Allow E packets to have type 1 */
2024                    recpkt[j++] = pbc[0];   
2025                    recpkt[j++] = pbc[1];
2026                    recpkt[j] = '\0';
2027                    if (xunchar(pbc[2]) == chk1(recpkt+lp))
2028                      break;
2029                    else { j -=2; recpkt[j] = '\0'; }
2030                }
2031                debug(F110,"checked chars",recpkt+lp,0);
2032                debug(F101,"block check","",xunchar(*pbc));
2033                debug(F101,"should be","",(int) chk3(recpkt+lp,parity));
2034                freerbuf(k);
2035                logpkt('r',-1,(CHAR *)"<crunched:chk3>");
2036                screen(SCR_PT,'%',(long)pktnum,"CRC error");
2037                return('Q');
2038            }
2039            break;
2040        case 4:                         /* Type 4 = Type 2, no blanks. */
2041            x = (unsigned)((xunchar(*pbc) - 1) << 6) |
2042                (unsigned)(xunchar(pbc[1]) - 1);
2043            if (x != chk2(recpkt+lp)) {
2044                if (type == 'E') {      /* Allow E packets to have type 1 */
2045                    recpkt[j++] = pbc[0];   
2046                    recpkt[j] = '\0';
2047                    if (xunchar(pbc[1]) == chk1(recpkt+lp))
2048                      break;
2049                    else
2050                      recpkt[--j] = '\0';
2051                }
2052                debug(F101,"bad type B block check","",x);
2053                freerbuf(k);
2054                logpkt('r',-1,(CHAR *)"<crunched:chkb>");
2055                screen(SCR_PT,'%',(long)pktnum,"Checksum error");
2056                return('Q');
2057            }
2058            break;
2059        default:                        /* Shouldn't happen... */
2060            freerbuf(k);
2061            logpkt('r',-1,(CHAR *)"<crunched:chkx>");
2062            screen(SCR_PT,'%',(long)pktnum,"(crunched)");
2063            return('Q');
2064    }
2065    debug(F101,"rpack block check OK","",rsn);
2066
2067/* Now we can believe the sequence number, and other fields. */
2068/* Here we violate strict principles of layering, etc, and look at the  */
2069/* packet sequence number.  If there's already a packet with the same   */
2070/* number in the window, we remove this one so that the window will not */
2071/* fill up. */
2072
2073    if ((x = rseqtbl[rsn]) != -1) {     /* Already a packet with this number */
2074        retrans++;                      /* Count it for statistics */
2075        debug(F101,"rpack got dup","",rsn);
2076        logpkt('r',rsn,(CHAR *)"<duplicate>");
2077        freerbuf(x);                    /* Free old buffer, keep new packet. */
2078        r_pkt[k].pk_rtr++;              /* Count this as a retransmission. */
2079    }
2080
2081/* New packet, not seen before, enter it into the receive window. */
2082
2083#ifdef CK_TIMERS
2084    rrttbl[rsn] = gtimer();             /* Timestamp */
2085#endif /* CK_TIMERS */
2086
2087    rseqtbl[rsn] = k;                   /* Make back pointer */
2088    r_pkt[k].pk_seq = rsn;              /* Record in packet info structure */
2089    r_pkt[k].pk_typ = type;             /* Sequence, type,... */
2090    r_pkt[k].pk_adr = rdatap;           /* pointer to data buffer */
2091    screen(SCR_PT,(char)type,(long)rsn,(char *)sohp); /* Update screen */
2092    return(type);                       /* Return packet type */
2093}
2094
2095/*  L O G P K T  --  Log packet number n, pointed to by s.  */
2096
2097/* c = 's' (send) or 'r' (receive) */
2098
2099VOID
2100#ifdef CK_ANSIC
2101logpkt(char c,int n, CHAR *s)
2102#else
2103logpkt(c,n,s) char c; int n; CHAR *s;
2104#endif /* CK_ANSIC */
2105/* logpkt */ {
2106    char plog[20];
2107    if (pktlog && *s) {
2108        if (n < 0)
2109          sprintf(plog,"%c-xx-%02d-",c,(gtimer()%60));
2110        else
2111          sprintf(plog,"%c-%02d-%02d-",c,n,(gtimer()%60));
2112        if (zsout(ZPFILE,plog) < 0) pktlog = 0;
2113        else if (zsoutl(ZPFILE,(char *)s) < 0) pktlog = 0;
2114    }
2115}
2116
2117#ifdef TLOG
2118
2119/*  T S T A T S  --  Record statistics in transaction log  */
2120
2121VOID
2122tstats() {
2123    char *tp;
2124    ztime(&tp);                         /* Get time stamp */
2125    tlog(F100,"","",0L);                /* Leave a blank line */
2126    tlog(F110,"Transaction complete",tp,0L);  /* Record it */
2127
2128    if (filcnt < 1) return;             /* If no files, done. */
2129
2130/* If multiple files, record character totals for all files */
2131
2132    if (filcnt > 1) {
2133        tlog(F101," files transferred       ","",filcnt - filrej);
2134        tlog(F101," total file characters   ","",tfc);
2135        tlog(F101," communication line in   ","",tlci);
2136        tlog(F101," communication line out  ","",tlco);
2137    }
2138
2139/* Record timing info for one or more files */
2140
2141    tlog(F101," elapsed time (seconds)  ","",(long) tsecs);
2142    if (tsecs > 0) {
2143        long lx;
2144        lx = (tfc * 10L) / (long) tsecs;
2145        tlog(F101," effective data rate     ","",lx/10L);
2146        if (speed <= 0L) speed = ttgspd();
2147#ifdef COMMENT
2148        if (speed > 0L && speed != 8880L && network == 0) {
2149            lx = (lx * 100L) / speed;
2150            tlog(F101," efficiency (percent)    ","",lx);
2151        }
2152#endif /* COMMENT */
2153    }
2154    tlog(F100,"","",0L);                /* Leave a blank line */
2155}
2156
2157/*  F S T A T S  --  Record file statistics in transaction log  */
2158
2159VOID
2160fstats() {
2161    tfc += ffc;
2162    if (!discard && !cxseen && !czseen && what != W_NOTHING)
2163      tlog(F101," complete, size","",ffc);
2164}
2165#else /* NOTLOG */
2166VOID
2167tstats() {}
2168
2169VOID
2170fstats() {
2171    tfc += ffc;
2172}
2173#endif /* TLOG */
Note: See TracBrowser for help on using the repository browser.