1 /* C K C F N 2 -- System-independent Kermit protocol support functions... */
3 /* ...Part 2 (continued from ckcfns.c) */
6 Author: Frank da Cruz <fdc@columbia.edu>,
7 Columbia University Academic Information Systems, New York City.
9 Copyright (C) 1985, 2004,
10 Trustees of Columbia University in the City of New York.
11 All rights reserved. See the C-Kermit COPYING.TXT file or the
12 copyright text in the ckcmai.c module for disclaimer and permissions.
15 Note -- if you change this file, please amend the version number and date at
16 the top of ckcfns.c accordingly.
19 #include "ckcsym.h" /* Compilation options */
20 #include "ckcdeb.h" /* Debugging and other symbols */
21 #include "ckcasc.h" /* ASCII symbols */
22 #include "ckcker.h" /* Kermit symbols */
23 #include "ckcxla.h" /* Translation */
24 #include "ckcnet.h" /* IKS and VMS #define TCPSOCKET */
25 #ifdef TCPSOCKET /* For TELNET business in spack() */
26 extern int tn_nlm, ttnproto, tn_b_nlm;
27 #endif /* TCPSOCKET */
29 extern int parity, network, local, interrupted, fatalio, wasclosed;
31 int kstartactive = 0; /* Flag for kstart() in a packet */
33 static CHAR p_tbl[] = { /* Even parity table for dopar(). */
34 (CHAR) '\000', /* ANSI C casts '\ooo' constants */
35 (CHAR) '\201', /* to signed char, so we have to */
36 (CHAR) '\202', /* cast back to unsigned char... */
164 /* D O P A R -- Add an appropriate parity bit to a character */
168 dopar(register CHAR ch)
170 dopar(ch) register CHAR ch;
171 #endif /* CK_ANSIC */
173 register unsigned int a;
176 || (network && (ttnproto == NP_TELNET) && (TELOPT_ME(TELOPT_BINARY)))
178 || (!local && sstelnet) /* TELNET BINARY MODE */
180 #endif /* TCPSOCKET */
181 ) return((CHAR) (ch & 255)); else a = ch & 127;
183 case 'e': return(p_tbl[a]); /* Even */
184 case 'm': return((CHAR) (a | 128)); /* Mark */
185 case 'o': return((CHAR) (p_tbl[a] ^ 128)); /* Odd */
186 case 's': return((CHAR) a); /* Space */
187 default: return((CHAR) a); /* Something illegal */
191 #ifndef NOXFER /* Rest of this file... */
193 #define NEWDPL /* New dynamic packet length method */
202 extern struct pktinfo *s_pkt; /* array of pktinfo structures */
203 extern struct pktinfo *r_pkt; /* array of pktinfo structures */
205 extern struct pktinfo s_pkt[]; /* array of pktinfo structures */
206 extern struct pktinfo r_pkt[]; /* array of pktinfo structures */
209 extern int sseqtbl[], rseqtbl[], sbufuse[], sacktbl[], wslots, winlo, wslotn,
210 sbufnum, rbufnum, pktpaus, reliable;
213 static int dontsend = 0;
214 extern int streaming;
215 #endif /* STREAMING */
217 extern int ttprty; /* from ck*tio.c */
220 extern int spsiz, spmax, rpsiz, timint, timef, npad, bestlen, maxsend;
221 extern int rpt, rptq, rptflg, capas, spsizf, en_fin, tsecs, flow;
222 extern int pktnum, sndtyp, rcvtyp, bctr, bctu, bctl, rsn, rln, maxtry, size;
223 extern int osize, maxsize, spktl, rpktl, nfils, stdouf, fsecs;
224 extern int turn, turnch, displa, pktlog, seslog, xflg, mypadn;
225 extern int hcflg, server, cxseen, czseen, discard, slostart;
226 extern int nakstate, quiet, success, xitsta, what, filestatus;
227 extern int spackets, rpackets, timeouts, retrans, crunched, urpsiz;
228 extern int carrier, fdispla, srvidl;
231 extern CKFLOAT fptsecs, fpfsecs, fpxfsecs;
234 extern long filcnt, filrej, ffc, flci, flco, tlci, tlco, tfc, speed;
235 extern long filcps, tfcps;
237 extern char *cmarg, filnam[];
239 extern CHAR padch, mypadc, eol, seol, ctlq, sstate;
240 extern CHAR *recpkt, *data, myinit[];
241 extern CHAR *srvptr, stchr, mystch, *rdatap;
242 extern CHAR padbuf[];
243 extern CHAR * epktmsg;
244 extern int epktrcvd, epktsent;
246 #ifdef OS2 /* AUTODOWNLOAD parameters */
247 extern int adl_kmode, adl_zmode; /* Match Packet to signal download */
248 extern char * adl_kstr; /* KERMIT Download String */
249 extern char * adl_zstr; /* ZMODEM Download String */
253 CHAR ksbuf[96] = { NUL, NUL }; /* Autodownload "Kermit Start" buf */
254 #endif /* CK_AUTODL */
256 int numerrs = 0; /* Number of packet errors so far */
257 int rcvtimo = 0; /* Timeout for receiving a packet */
258 int idletmo = 0; /* Flag for idle timeout */
260 long filcps = 0L; /* CPS most recent file transferred */
261 long tfcps = 0L; /* CPS most recent transaction */
262 long xfsecs = 0L; /* Elapsed time for most recent file */
264 CKFLOAT fpxfsecs = 0.0; /* Ditto, but floating point */
268 int rrttbl[64], srttbl[64]; /* Packet timestamp tables */
270 #define RTT_SCALE 1000
272 rttsamples, /* Round trip time samples */
273 rttdelay, /* RTT delay */
274 pktintvl, /* Interpacket arrival time */
275 rttvariance, /* RTT variance */
276 rttstddev; /* RTT standard deviation */
277 #endif /* CK_TIMERS */
279 /* CRC generation tables */
281 long crcta[16] = { 0L, 010201L, 020402L, 030603L, 041004L,
282 051205L, 061406L, 071607L, 0102010L, 0112211L, 0122412L, 0132613L, 0143014L,
283 0153215L, 0163416L, 0173617L
286 long crctb[16] = { 0L, 010611L, 021422L, 031233L, 043044L,
287 053655L, 062466L, 072277L, 0106110L, 0116701L, 0127532L, 0137323L, 0145154L,
288 0155745L, 0164576L, 0174367L
293 Round-trip timer calculations adapted from Tim Kientzle's article,
294 "Improving Kermit Performance", Dr Dobb's Journal, February 1996.
298 /* R T T I N I T -- Initialize timers at start of transaction */
301 rttinit() { /* Initialize round-trip timing */
307 rttsamples = 0L; /* Samples (packets) */
308 rttvariance = 0L; /* Variance in delay */
309 rttdelay = (long) timint * RTT_SCALE; /* Delay */
310 pktintvl = (long) timint * RTT_SCALE; /* Delay */
311 rttstddev = (long) timint * RTT_SCALE; /* Standard deviation of delay */
313 /* Tables of timestamps indexed by packet sequence number */
315 for (i = 0; i < 64; i++) {
316 rrttbl[i] = -1; /* Time each packet was received */
317 srttbl[i] = -1; /* Time each packet was sent */
319 rcvtimo = timint; /* Initial timeout is what user said */
322 /* G E T R T T -- Get packet round trip time */
324 Call with nakstate == 0 if file sender, nonzero if receiver,
325 and n == packet sequence number of the packet we just received.
328 -1 on failure with rcvtimo set to timint (what the user said), or:
329 0 on success with rcvtimo set to dynamically calculated value:
330 1 <= rcvtimo <= timint * 3.
333 getrtt(nakstate, n) int nakstate, n; {
334 extern int mintime, maxtime;
335 static int prevz = 0, prevr = 0;
336 int x, y, yy, z = 0, zz = 0; /* How long did it take to get here? */
338 rcvtimo = timint; /* Default timeout is what user said */
340 if (timint == 0) /* We're not timing out. */
343 if (!rttflg) /* Not supposed to be doing this? */
344 return(-1); /* So don't */
346 if (!RTT_SCALE) /* Paranoia... */
349 /* rtimer() (reset timer) is not called until 1st data packet */
353 /* S (F [ A ] D* Z)* B */
355 /* NOTE: we calculate both the round-trip time AND the packet */
356 /* arrival rate. We don't use the RTT for anything, we just display it. */
357 /* Timeouts are based on the packet arrival rate. */
359 if (spackets > 3) { /* Don't start till 4th packet */
360 if (nakstate) { /* File receiver */
361 x = rrttbl[n]; /* Time when I got packet n */
362 y = rrttbl[n > 0 ? n - 1 : 63]; /* Time when I got packet n-1 */
363 yy = srttbl[n > 0 ? n - 1 : 63]; /* Time when I sent ACK(n-1) */
364 if (x > -1 && y > -1) { /* Be careful */
365 z = x - y; /* Packet rate */
366 zz = x - yy; /* Round trip time */
367 z++; /* So sender & receiver differ */
368 debug(F101,"RTT RECV","",z);
369 } else { /* This shouldn't happen */
370 debug(F101,"RTT RECV ERROR spackets","",spackets);
371 debug(F101,"RTT RECV ERROR sequence","",n);
374 } else { /* File sender */
375 x = rrttbl[n]; /* Time when I got ACK(n) */
376 y = rrttbl[n > 0 ? n - 1 : 63]; /* Time when I got packet n-1 */
377 yy = srttbl[n]; /* Time when I sent n */
378 if (x > -1 && y > -1) {
379 z = x - y; /* Packet rate */
380 zz = x - yy; /* Round trip time */
381 debug(F101,"RTT SEND","",z);
383 debug(F100,"RTT SEND ERROR","",0);
387 if (z < 1) /* For fast connections */
388 z = RTT_SCALE / 2; /* Convert to scale... */
391 debug(F101,"RTT z scaled","",z);
393 if (zz < 1) /* For fast connections */
394 zz = RTT_SCALE / 2; /* Convert to scale... */
398 rttdelay = zz; /* Round trip time of this packet */
401 This was used in C-Kermit 7.0 (and 6.0?) but not only is it overkill,
402 it also can produce ridiculously long timeouts under certain conditions.
403 Replaced in 8.0 by a far simpler and more aggressive strategy.
405 if (rttsamples++ == 0L) { /* First sample */
407 } else { /* Subsequent samples */
408 long oldavg = pktintvl;
411 if (rttsamples > 30) /* Use real average for first 30 */
412 rttsamples = 30; /* then decaying average. */
414 /* Average delay, difference squared, variance, std deviation */
416 pktintvl += (z - pktintvl) / rttsamples;
417 rttdiffsq = (z - oldavg) * (z - oldavg);
418 rttvariance += (rttdiffsq - rttvariance) / rttsamples;
419 debug(F101,"RTT stddev1","",rttstddev);
420 if (rttstddev < 1L) /* It can be zero, in which case */
421 rttstddev = RTT_SCALE / 3; /* set it to something small... */
422 rttstddev = (rttstddev + rttvariance / rttstddev) / 2;
424 debug(F101,"RTT stddev2","",rttstddev);
425 debug(F101,"RTT delay ","",pktintvl);
426 rcvtimo = (pktintvl + (3L * rttstddev)) / RTT_SCALE + 1;
427 if (rpackets < 32) /* Allow for slow start */
428 rcvtimo += rcvtimo + 2;
429 else if (rpackets < 64)
430 rcvtimo += rcvtimo / 2 + 1;
431 /* On a reliable link, don't try too hard to time out. */
432 /* Especially on fast local network connections. */
433 if (server && what == W_NOTHING) /* Server command wait */
434 rcvtimo = rcvtimo; /* == srvtim */
435 else if (reliable == SET_ON && rcvtimo > 0) /* Reliable */
436 rcvtimo = rcvtimo +15; /* and not server command wait */
437 else /* Not reliable or server cmd wait */
439 if (rcvtimo < mintime) /* Lower bound */
441 if (maxtime > 0) { /* User specified an upper bound */
442 if (rcvtimo > maxtime)
444 } else if (maxtime == 0) { /* User didn't specify */
445 if (rcvtimo > timint * 6)
446 rcvtimo = timint * 6;
452 x = (CKFLOAT)(prevz + z + z) / 3.0;
453 rcvtimo = (int)((((CKFLOAT)x * 2.66) / RTT_SCALE) + 0.5);
454 debug(F101,"RTT rcvtimo (float)","",rcvtimo);
457 rcvtimo = (prevz + z + z) / RTT_SCALE;
458 debug(F101,"RTT rcvtimo (int)","",rcvtimo);
462 zz = (rttdelay + 500) / 1000;
463 if (rcvtimo > (zz * 3))
469 if (rcvtimo < mintime) /* Lower bound */
472 if (maxtime > 0) { /* Upper bound */
473 if (rcvtimo > maxtime)
476 if (rcvtimo == (prevr - 1))
479 debug(F101,"RTT final rcvtimo","",rcvtimo);
485 #endif /* CK_TIMERS */
487 /* I N P U T -- Attempt to read packet number 'pktnum'. */
490 This is the function that feeds input to Kermit's finite state machine,
491 in the form of a character in the range 32-126, normally a packet type
492 (uppercase letter) or pseudo-packet-type (lowercase letter).
494 If a special start state is in effect, that state is returned as if it were
495 the type of an incoming packet.
499 int type = 0, acktype; /* Received packet type */
500 int x, y, k; /* Workers */
501 int z, pi, nf; /* Worker, packet index, NAK flag */
504 debug(F000,"input sstate","",sstate);
505 debug(F101,"input nakstate","",nakstate);
506 debug(F000,"input sndtyp","",sndtyp);
507 debug(F101,"input xitsta","",xitsta);
508 debug(F101,"input what","",what);
510 while (1) { /* Big loop... */
512 It is ttchk()'s responsibility to tell us if the connection is broken,
513 and to do so instantly and nondestructively -- no blocking, etc, that would
514 slow down file transfer.
517 debug(F100,"input CONNECTION BROKEN","",0);
521 if (sstate != 0) { /* If a start state is in effect, */
522 type = sstate; /* return it like a packet type, */
523 sstate = 0; /* and then nullify it. */
524 numerrs = 0; /* (PWP) no errors so far */
527 if (nakstate) { /* This section for file receiver. */
528 if (wslots > 1) { /* If we're doing windows, */
529 x = rseqtbl[winlo]; /* see if desired packet already in. */
530 debug(F101,"input winlo","",winlo);
531 debug(F101,"input rseqtbl[winlo]","",rseqtbl[winlo]);
532 if (x > -1) { /* Already there? */
533 if (r_pkt[x].pk_seq == winlo) { /* (double check) */
534 rsn = winlo; /* Yes, return its info */
535 debug(F101,"input return pre-stashed packet","",rsn);
537 rdatap = r_pkt[x].pk_adr; /* like rpack would do. */
538 rln = (int)strlen((char *) rdatap);
539 type = r_pkt[x].pk_typ;
544 type = rpack(); /* Try to read a packet. */
545 debug(F101,"input rpack","",type);
547 while (type == 'e') { /* Handle echoes */
548 debug(F101,"input echo discarded","",type);
554 debug(F011,"input type D=",(char *)rdatap,39);
556 debug(F000,"input type",(char *)rdatap,type);
562 errpkt((CHAR *)"User cancelled.");
566 #endif /* OLDCHKINT */
570 "FAILED - Interrupted" :
571 "FAILED - Connection lost";
573 xxscreen(SCR_PT,'q',0L,s);
575 return('q'); /* Ctrl-C or connection lost */
577 if (type < 0) { /* Receive window full */
578 /* Another thing to do here would be to delete */
579 /* the highest packet and NAK winlo. But that */
580 /* shouldn't be necessary since the other Kermit */
581 /* should not have sent a packet outside the window. */
584 ckmakxmsg(foo,256,"Receive window full (rpack): wslots=",
585 ckitoa(wslots)," winlo=",ckitoa(winlo)," pktnum=",
586 ckitoa(pktnum), NULL,NULL,NULL,NULL,NULL,NULL);
588 debug(F100,foo,"",0);
590 errpkt((CHAR *)"Receive window full");
591 debug(F101,"rpack receive window full","",0);
592 debug(F101," wslots","",wslots);
593 debug(F101," winlo","",winlo);
594 debug(F101," pktnum","",pktnum);
603 if (chkint() < 0) { /* Check for console interrupts. */
604 errpkt((CHAR *)"User cancelled."); /* (old way) */
608 #endif /* OLDCHKINT */
611 if (streaming) { /* Streaming */
612 if (type == 'Q' || type == 'T') { /* Errors are fatal. */
613 crunched++; /* For statistics */
614 errpkt((CHAR *)"Transmission error on reliable link.");
618 #endif /* STREAMING */
620 debug(F101,"input got E, nakstate","",nakstate);
621 break; /* Error packet */
623 if (type == 'Q') { /* Crunched packet. */
627 Packet arrived damaged. It was most likely the packet we were expecting
628 next, so we send a NAK for that packet. Prior to 5A(189), we always
629 NAK'd winlo here, but that was bad because if two (or more) different
630 packets were damaged, we would keep NAKing the first one and never NAK the
631 other ones, which could result in a lengthy series of timeouts. Now we
632 NAK the oldest as-yet-unNAK'd missing packet.
635 rcvtimo++; /* Stretch the timeout a little */
636 #endif /* CK_TIMERS */
637 z = (winlo + wslots) % 64; /* Search from winlo to z */
638 debug(F101,"ZZZ crunched z","",z);
639 nf = 0; /* NAK flag not set yet */
640 for (x = winlo; x != z; x = (x + 1) % 64) {
641 debug(F101,"ZZZ x","",x);
642 if (rseqtbl[x] > -1) /* Have I received packet x? */
643 continue; /* Yes, go on. */
644 debug(F101,"ZZZ x not recd yet","",x);
645 pi = sseqtbl[x]; /* No, have I NAK'd it yet? */
646 if (pi < 0 || s_pkt[pi].pk_rtr == 0) {
647 debug(F101,"ZZZ x not NAK'd yet","",x);
648 nack(x); /* No, NAK it now. */
649 nf = 1; /* Flag that I did. */
653 if (!nf) { /* If we didn't NAK anything above, */
654 debug(F101,"ZZZ NAKing winlo","",winlo);
655 if (nack(winlo) < 0) { /* we have to NAK winlo (again) */
656 errpkt((CHAR *)"Too many retries."); /* Too many */
664 if (type == 'T') { /* Timeout */
666 /* K95 does this its own way */
667 if (server && srvidl) {
669 debug(F101,"SERVER IDLE TIMEOUT","",srvidl);
674 rcvtimo++; /* Stretch the timeout a little */
675 #endif /* CK_TIMERS */
677 debug(F101,"input receive-state timeout, winlo","",winlo);
678 /* NAK only the packet at window-low */
679 debug(F101,"input sending NAK for winlo","",winlo);
681 if (x > 0) /* Don't give up if there is still */
682 continue; /* something to read. */
686 return('q'); /* Connection Lost */
688 if (nack(winlo) < 0) {
689 debug(F101,"input sent too many naks","",winlo);
690 errpkt((CHAR *)"Too many retries.");
695 if (rsn == winlo) { /* Got the packet we want, done. */
697 if (rttflg && timint) /* Dynamic round trip timers? */
698 getrtt(nakstate, rsn); /* yes, do it. */
699 #endif /* CK_TIMERS */
700 debug(F101,"input rsn=winlo","",rsn);
704 /* Got a packet out of order. */
706 debug(F101,"input out of sequence, rsn","",rsn);
707 k = rseqtbl[rsn]; /* Get window slot of this packet. */
708 debug(F101,"input rseqtbl[rsn]","",k);
710 debug(F101,"input recv can't find index for rcvd pkt","",rsn);
711 /* Was "Internal error 21" */
712 /* This should not happen */
713 errpkt((CHAR *)"Sliding windows protocol error.");
717 y = chkwin(rsn,winlo,wslots); /* See what window it's in. */
718 debug(F101,"input recv chkwin","",y);
719 if (y == 1) { /* From previous window. */
721 if (!streaming) /* NO RESEND IF STREAMING! */
722 #endif /* STREAMING */
723 resend(rsn); /* Resend the ACK (might have data) */
724 freerpkt(rsn); /* Get rid of received packet */
725 continue; /* Back to wait for another packet */
726 } else { /* In this window or out of range */
727 if (y < 0) /* If out of range entirely, */
728 freerpkt(rsn); /* release its buffer */
731 if (streaming) { /* Streaming (this shouldn't happen) */
732 errpkt((CHAR *)"Sequence error on reliable link.");
736 #endif /* STREAMING */
738 /* If our receive window is full, NAK window-low */
740 if (rbufnum < 1) { /* Receive window full? */
741 if (nack(winlo) < 0) { /* No choice, must NAK winlo. */
742 errpkt((CHAR *)"Too many retries."); /* Too many */
748 Receive window not full. This is a packet in the current window but it is
749 not the desired packet at winlo. So therefore there are gaps before this
750 packet. So we find the "lowest" unNAK'd missing packet, if any, between
751 winlo and this one, and NAK it. If there are no as-yet-unNAK'd missing
752 packets in the window, then we send nothing and go wait for another packet.
753 In theory, this could result in a timeout, but in practice it is likely that
754 the already-NAK'd missing packets are already on their way. Note, we do not
755 NAK ahead of ourselves, as that only creates unnecessary retransmissions.
757 for (x = winlo; x != rsn; x = (x + 1) % 64) {
758 if (rseqtbl[x] > -1) /* Have I received packet x? */
759 continue; /* Yes, check next sequence number. */
760 pi = sseqtbl[x]; /* No, have I NAK'd it yet? */
761 if (pi < 0 || s_pkt[pi].pk_rtr == 0) {
762 nack(x); /* No, NAK it now. */
768 } else { /* Otherwise file sender... */
771 if (streaming && sndtyp == 'D') {
772 debug(F101,"STREAMING input streaming","",streaming);
773 debug(F000,"STREAMING input sndtyp","",sndtyp);
775 type = 'Y'; /* Pretend we got an ACK */
777 #endif /* STREAMING */
778 if (!nak2ack) { /* NAK(n+1) = ACK(n) */
779 if (wslots > 1) { /* Packet at winlo already ACK'd? */
780 if (sacktbl[winlo]) { /* If so, */
781 sacktbl[winlo] = 0; /* Turn off the ACK'd flag */
782 winlo = (winlo + 1) % 64; /* Rotate the window */
783 type = 'Y'; /* And return ACK */
785 "input send returning pre-stashed ACK","",
791 if (!(streaming && sndtyp == 'D')) { /* Not streaming | data */
792 type = rpack(); /* Try to read an acknowledgement */
793 } else { /* Streaming and in Data phase */
794 type = 'Y'; /* Assume all is normal */
795 if (chkint() < 0) /* Check for console interrupts. */
797 else if (ttchk() > 4 + bctu) /* Check for return traffic */
799 debug(F000,"input streaming type","",type);
801 #endif /* STREAMING */
802 debug(F111,"input send",(char *) rdatap,(int) type);
803 while (type == 'e') { /* Handle echoes */
804 debug(F000,"echo discarded","",type);
810 errpkt((CHAR *)"User cancelled.");
814 #endif /* OLDCHKINT */
816 xxscreen(SCR_PT,'q',0L,
817 ((char *)((type == -2) ?
823 return('q'); /* Ctrl-C or connection lost */
829 "Receive window full (error 18): wslots=",
831 " winlo=",ckitoa(winlo)," pktnum=",
832 ckitoa(pktnum), NULL,NULL,NULL,NULL,NULL,NULL);
834 debug(F100,foo,"",0);
836 errpkt((CHAR *)"Receive window full"); /* was "internal */
837 debug(F101," wslots","",wslots); /* error 18" */
838 debug(F101," winlo","",winlo);
839 debug(F101," pktnum","",pktnum);
845 dumprbuf(); /* Debugging */
848 if (chkint() < 0) { /* Check for console interrupts. */
849 errpkt((CHAR *)"User cancelled.");
852 #endif /* OLDCHKINT */
857 if (streaming) { /* Streaming */
858 if (type == 'Q' || type == 'T') { /* Errors are fatal. */
859 crunched++; /* For statistics */
860 errpkt((CHAR *)"Transmission error on reliable link.");
864 #endif /* STREAMING */
866 debug(F101,"input send got E, nakstate","",nakstate);
867 break; /* Error packet */
869 if (type == 'Q') { /* Crunched packet */
870 crunched++; /* For statistics */
871 numerrs++; /* For packet resizing */
872 x = resend(winlo); /* Resend window-low */
875 errpkt((CHAR *)"Too many retries");
880 if (type == 'T') { /* Timeout waiting for ACKs. */
881 timeouts++; /* Count it */
882 numerrs++; /* Count an error too */
883 debug(F101,"input send state timeout, winlo","",winlo);
885 /* Retransmit the oldest un-ACK'd packet. */
887 debug(F101,"input send resending winlo","",winlo);
888 if (resend(winlo) < 0) { /* Check retries */
889 debug(F101,"input send too many resends","",maxtry);
890 errpkt((CHAR *)"Too many retries");
894 /* Reduce prevailing packet length */
895 x = sseqtbl[winlo]; /* Get length of packet we want ACKd */
896 if (x > -1) { /* Only if we have a valid index */
897 if (s_pkt[x].pk_typ == 'D') { /* only for D packets */
898 spsiz = (s_pkt[x].pk_len + 8) >> 1; /* halve it */
899 if (spsiz < 20) spsiz = 20; /* within reason */
900 debug(F101,"input T cut packet length","",spsiz);
907 /* Got an actual normal packet */
909 nak2ack = 0; /* Unset this flag. */
910 y = chkwin(rsn,winlo,wslots); /* Is it in the window? */
911 debug(F101,"input send rsn","",rsn);
912 debug(F101,"input send winlo","",winlo);
913 debug(F101,"input send chkwin","",y);
915 if (type == 'Y') { /* Got an ACK */
916 if (y == 0) { /* In current window */
917 if (spackets < 4) /* Error counter doesn't count */
918 numerrs = 0; /* until data phase. */
919 sacktbl[rsn]++; /* Mark the packet as ACK'd */
920 x = sseqtbl[rsn]; /* Get ACK'd packet's buffer index */
921 debug(F101,"bestlen ack x","",x);
924 acktype = s_pkt[x].pk_typ; /* Get type */
925 debug(F000,"bestlen ack type","",acktype);
927 if (acktype == 'D') { /* Adjust data packet length */
928 if (spsiz > bestlen) {
930 debug(F101,"bestlen B","",bestlen);
934 debug(F101,"bestlen retry","",s_pkt[x].pk_rtr);
935 debug(F101,"bestlen len","",s_pkt[x].pk_len);
936 debug(F101,"bestlen spackets","",spackets);
939 /* Set new best length */
940 if (s_pkt[x].pk_rtr == 0 &&
941 s_pkt[x].pk_len + 8 > bestlen) {
942 bestlen = s_pkt[x].pk_len + 8;
945 debug(F101,"bestlen A","",bestlen);
949 debug(F101,"bestlen wslots","",wslots);
950 debug(F101,"bestlen maxsend","",maxsend);
955 (maxsend <= spmax) &&
959 debug(F101,"bestlen spsiz A","",spsiz);
961 /* Creep up to best length */
962 } else if ((spackets > 5) &&
963 (spsiz < bestlen - 8)) {
964 spsiz += (bestlen - spsiz) / 3;
965 debug(F101,"bestlen spsiz B","",spsiz);
967 /* Push the envelope */
968 } else if ((spackets % (wslots + 1) == 0) &&
970 (bestlen < spmax - 8) &&
972 spsiz += (spmax - bestlen) / 3;
973 debug(F101,"bestlen spsiz C","",spsiz);
975 /* But not too far */
978 debug(F101,"bestlen spsiz D","",spsiz);
985 if (rttflg && timint) /* If doing dynamic timers */
986 getrtt(nakstate, rsn); /* call routine to set it. */
987 #endif /* CK_TIMERS */
989 NOTE: The following statement frees the buffer of the ACK we just got.
990 But the upper layers still need the data, like if it's the ACK to an I,
991 S, F, D, Z, or just about any kind of packet. So for now, freerbuf()
992 deallocates the buffer, but does not erase the data or destroy the pointer
993 to it. There's no other single place where these receive buffers can be
994 correctly freed (?) ...
996 freerpkt(rsn); /* Free the ACK's buffer */
997 freesbuf(rsn); /* *** Free the sent packet's buffer */
998 if (rsn == winlo) { /* Got the one we want */
1000 winlo = (winlo + 1) % 64;
1001 debug(F101,"input send rotated send window","",winlo);
1002 break; /* Return the ACK */
1004 debug(F101,"input send mark pkt","",rsn);
1005 continue; /* Otherwise go read another packet */
1007 } else if (y == 1 && wslots < 2) { /* (190) ACK for previous */
1008 numerrs++; /* == NAK for current, count error */
1009 debug(F101,"input send ACK for previous","",rsn);
1010 freerpkt(rsn); /* Free NAK's buffer */
1011 x = resend(winlo); /* Resend current packet */
1014 errpkt((CHAR *)"Too many retries");
1016 } else continue; /* Resend ok, go read another packet */
1017 } else { /* Other cases, just ignore */
1018 debug(F101,"input send ACK out of window","",rsn);
1023 if (type == 'N') { /* NAK */
1024 numerrs++; /* Count an error */
1026 if (streaming) { /* Streaming */
1027 errpkt((CHAR *)"NAK received on reliable link.");
1031 #endif /* STREAMING */
1033 debug(F101,"input send NAK","",rsn);
1035 /* Reduce prevailing packet length */
1036 x = sseqtbl[rsn]; /* Length of packet that was NAK'd */
1037 if (x > -1) { /* If it's a Data packet we've sent */
1038 if (s_pkt[x].pk_typ == 'D') {
1039 spsiz = (s_pkt[x].pk_len + 8) >> 1; /* Halve length */
1041 /* This might be a good idea -- haven't tried it ... */
1042 if (bestlen > 0 && spsiz > bestlen)
1044 #endif /* COMMENT */
1045 if (spsiz < 20) spsiz = 20;
1046 debug(F101,"input N cut packet length","",spsiz);
1050 freerpkt(rsn); /* Free buffer where NAK lies. */
1051 if (y == 0) { /* In current window */
1052 debug(F100," in window","",0);
1053 k = sseqtbl[rsn]; /* Get pointer to NAK'd packet. */
1054 if (k < 0 || (k > -1 && s_pkt[k].pk_typ == ' ')) {
1055 x = resend(winlo); /* Packet we haven't sent yet. */
1057 x = resend(rsn); /* Resend requested packet. */
1059 if (x < 0) { /* Resend error is fatal. */
1061 errpkt((CHAR *)"Too many retries");
1063 } else continue; /* Resend ok, go read another packet */
1064 } else if ((rsn == (pktnum + 1) % 64)) { /* NAK for next pkt */
1066 debug( F101,"NAK for next packet, windowing","",rsn);
1067 x = resend(winlo); /* Resend window-low */
1070 errpkt((CHAR *)"Too many retries");
1073 continue; /* Go back and read another pkt */
1075 debug(F101,"NAK for next packet, no windowing","",rsn);
1076 x = (rsn == 0) ? 63 : rsn - 1;
1077 if (x == 0 && (sndtyp == 'S' || sndtyp == 'I')) {
1078 resend(0); /* ACK for S or I packet missing */
1079 continue; /* so resend the S or I */
1081 rsn = x; /* Else, treat NAK(n+1) as ACK(n) */
1082 nak2ack = 1; /* Go back and process the ACK */
1084 } else if (y > 0) { /* NAK for pkt we can't resend */
1085 debug(F101," NAK out of window","",rsn); /* bad... */
1087 errpkt((CHAR *)"NAK out of window");
1089 } else continue; /* Ignore other NAKs */
1090 } /* End of file-sender NAK handler */
1092 if (rsn == winlo) { /* Not ACK, NAK, timeout, etc. */
1093 debug(F000,"input send unexpected type","",type);
1096 } /* End of file-sender section */
1097 } /* End of input() while() loop */
1099 When the window size is 1 and we have the packet we want, there can not
1100 possibly be anything waiting for us on the connection that is useful to us.
1101 However, there might be redundant copies of a packet we already got, which
1102 would cause needless cycles of repeated packets. Therefore we flush the
1103 communications input buffer now to try to get rid of undesired and unneeded
1104 packets that we have not read yet.
1106 if (wslotn == 1 /* (not wslots!) */
1108 && !streaming /* But not when streaming */
1109 #endif /* STREAMING */
1111 debug(F100,"input about to flush","",0);
1112 ttflui(); /* Got what we want, clear input buffer. */
1115 if (!nakstate) /* When sending */
1116 rcalcpsz(); /* recalculate size every packet */
1119 xitsta |= (what ? what : 1); /* Remember what failed. */
1120 debug(F101,"input winlo","",winlo);
1121 debug(F101,"input rsn","",rsn);
1122 debug(F000,"input returning type","",type);
1123 return(rcvtyp = type); /* Success, return packet type. */
1127 /* P A R C H K -- Check if Kermit packet has parity */
1130 Call with s = pointer to packet, start = packet start character, n = length.
1131 Returns 0 if packet has no parity, -1 on error, or, if packet has parity:
1132 'e' for even, 'o' for odd, 'm' for mark. Space parity cannot be sensed.
1133 So a return value of 0 really means either space or none.
1134 Returns -2 if parity has already been checked during this protocol operation.
1138 parchk(CHAR *s, CHAR start, int n)
1140 parchk(s,start,n) CHAR *s, start; int n;
1141 #endif /* CK_ANSIC */
1143 CHAR s0, s1, s2, s3;
1145 debug(F101,"parchk n","",n);
1146 debug(F101,"parchk start","",start);
1148 s0 = s[0] & 0x7f; /* Mark field (usually Ctrl-A) */
1150 if (s0 != start || n < 5) return(-1); /* Not a valid packet */
1152 /* Look at packet control fields, which never have 8th bit set */
1153 /* First check for no parity, most common case. */
1155 if (((s[0] | s[1] | s[2] | s[3]) & 0x80) == 0)
1156 return(0); /* No parity or space parity */
1158 /* Check for mark parity */
1160 if (((s[0] & s[1] & s[2] & s[3]) & 0x80) == 0x80)
1161 return('m'); /* Mark parity */
1163 /* Packet has some kind of parity */
1164 /* Make 7-bit copies of control fields */
1166 s1 = s[1] & 0x7f; /* LEN */
1167 s2 = s[2] & 0x7f; /* SEQ */
1168 s3 = s[3] & 0x7f; /* TYPE */
1170 /* Check for even parity */
1172 if ((s[0] == p_tbl[s0]) &&
1173 (s[1] == p_tbl[s1]) &&
1174 (s[2] == p_tbl[s2]) &&
1175 (s[3] == p_tbl[s3]))
1178 /* Check for odd parity */
1180 if ((s[0] != p_tbl[s0]) &&
1181 (s[1] != p_tbl[s1]) &&
1182 (s[2] != p_tbl[s2]) &&
1183 (s[3] != p_tbl[s3]))
1186 /* Otherwise it's probably line noise. Let checksum calculation catch it. */
1190 #endif /* PARSENSE */
1193 Check to make sure timeout intervals are long enough to allow maximum
1194 length packets to get through before the timer goes off. If not, the
1195 timeout interval is adjusted upwards.
1197 This routine is called at the beginning of a transaction, before we
1198 know anything about the delay characteristics of the line. It works
1199 only for serial communication devices; it trusts the speed reported by
1200 the operating system.
1202 Call with a timout interval. Returns it, adjusted if necessary.
1205 chktimo(timo,flag) int timo, flag; {
1206 long cps, z; int x, y;
1208 debug(F101,"chktimo streaming","",streaming);
1211 #endif /* STREAMING */
1213 debug(F101,"chktimo timo","",timo); /* Timeout before adjustment */
1214 debug(F101,"chktimo flag","",flag);
1216 if (flag) /* Don't change timeout if user */
1217 return(timo); /* gave SET SEND TIMEOUT command. */
1218 debug(F101,"chktimo spmax","",spmax);
1219 debug(F101,"chktimo urpsiz","",urpsiz);
1221 if (!network) { /* On serial connections... */
1222 speed = ttgspd(); /* Get current speed. */
1224 cps = speed / 10L; /* Convert to chars per second */
1226 long plen; /* Maximum of send and rcv pkt size */
1227 z = cps * (long) timo; /* Chars per timeout interval */
1228 z -= z / 10L; /* Less 10 percent */
1230 if (urpsiz > spmax) plen = urpsiz;
1231 debug(F101,"chktimo plen","",plen);
1232 if (z < plen) { /* Compare with packet size */
1233 x = (int) ((long) plen / cps); /* Adjust if necessary */
1234 y = x / 10; /* Add 10 percent for safety */
1235 if (y < 2) y = 2; /* Or 2 seconds, whichever is more */
1237 if (x > timo) /* If this is greater than current */
1238 timo = x; /* timeout, change the timeout */
1239 debug(F101,"chktimo new timo","",timo);
1247 /* S P A C K -- Construct and send a packet */
1250 spack() sends a packet of the given type, sequence number n, with len data
1251 characters pointed to by d, in either a regular or extended- length packet,
1252 depending on len. Returns the number of bytes actually sent, or else -1
1253 upon failure. Uses global npad, padch, mystch, bctu, data. Leaves packet
1254 fully built and null-terminated for later retransmission by resend().
1255 Updates global sndpktl (send-packet length).
1257 NOTE: The global pointer "data" is assumed to point into the 7th position
1258 of a character array (presumably in packet buffer for the current packet).
1259 It was used by getpkt() to build the packet data field. spack() fills in
1260 the header to the left of the data pointer (the data pointer is defined
1261 in getsbuf() in ckcfn3.c). If the address "d" is the same as "data", then
1262 the packet's data field has been built "in place" and need not be copied.
1266 spack(char pkttyp, int n, int len, CHAR *d)
1268 spack(pkttyp,n,len,d) char pkttyp; int n, len; CHAR *d;
1269 #endif /* CK_ANSIC */
1272 int ix, j, k, x, lp, longpkt, copy, loglen;
1275 CKFLOAT t1 = 0.0, t2 = 0.0;
1276 #endif /* GFTIMER */
1278 register CHAR *cp, *mydata;
1281 copy = (d != data); /* Flag whether data must be copied */
1284 if (deblog) { /* Save lots of function calls! */
1285 debug(F101,"spack n","",n);
1286 if (pkttyp != 'D') { /* Data packets would be too long */
1287 debug(F111,"spack data",data,data);
1288 debug(F111,"spack d",d,d);
1290 debug(F101,"spack len","",len);
1291 debug(F101,"spack copy","",copy);
1295 longpkt = (len + bctl + 2) > 94; /* Decide whether it's a long packet */
1296 mydata = data - 7 + (longpkt ? 0 : 3); /* Starting position of header */
1297 k = sseqtbl[n]; /* Packet structure info for pkt n */
1299 if (deblog) { /* Save 2 more function calls... */
1300 debug(F101,"spack mydata","",mydata);
1301 debug(F101,"spack sseqtbl[n]","",k);
1305 #endif /* STREAMING */
1306 debug(F101,"spack sending packet out of window","",n);
1311 s_pkt[k].pk_adr = mydata; /* Remember address of packet. */
1312 s_pkt[k].pk_seq = n; /* Record sequence number */
1313 s_pkt[k].pk_typ = pkttyp; /* Record packet type */
1315 spktl = 0; /* Initialize length of this packet */
1316 i = 0; /* and position in packet. */
1318 /* Now fill the packet */
1320 mydata[i++] = mystch; /* MARK */
1321 lp = i++; /* Position of LEN, fill in later */
1323 mydata[i++] = tochar(n); /* SEQ field */
1324 mydata[i++] = pkttyp; /* TYPE field */
1325 j = len + bctl; /* Length of data + block check */
1326 if (longpkt) { /* Long packet? */
1327 int x; /* Yes, work around SCO Xenix/286 */
1330 #endif /* CKTUNING */
1331 x = j / 95; /* compiler bug... */
1332 mydata[lp] = tochar(0); /* Set LEN to zero */
1333 mydata[i++] = tochar(x); /* Extended length, high byte */
1334 mydata[i++] = tochar(j % 95); /* Extended length, low byte */
1336 /* Header checksum - skip the function calls and loops */
1337 chk = (unsigned) mydata[lp] +
1338 (unsigned) mydata[lp+1] +
1339 (unsigned) mydata[lp+2] +
1340 (unsigned) mydata[lp+3] +
1341 (unsigned) mydata[lp+4] ;
1342 mydata[i++] = tochar((CHAR) ((((chk & 0300) >> 6) + chk) & 077));
1344 mydata[i] = '\0'; /* Terminate for header checksum */
1345 mydata[i++] = tochar(chk1(mydata+lp,5));
1346 #endif /* CKTUNING */
1347 } else mydata[lp] = tochar(j+2); /* Normal LEN */
1349 When sending a file, the data is already in the right place. If it weren't,
1350 it might make sense to optimize this section by using memcpy or bcopy
1351 (neither of which are portable), but only if our packets were rather long.
1352 When receiving, we're only sending ACKs so it doesn't matter. So count the
1353 following loop as a sleeping dog.
1355 if (copy) /* Data field built in place? */
1356 for ( ; len--; i++) mydata[i] = *d++; /* No, must copy. */
1357 else /* Otherwise, */
1358 i += len; /* Just skip past data field. */
1359 mydata[i] = '\0'; /* Null-terminate for checksum calc. */
1361 switch (bctu) { /* Block check */
1362 case 1: /* 1 = 6-bit chksum */
1363 ix = i - lp; /* Avoid "order of operation" error */
1364 mydata[i++] = tochar(chk1(mydata+lp,ix));
1366 case 2: /* 2 = 12-bit chksum */
1367 j = chk2(mydata+lp,i-lp);
1368 mydata[i++] = (unsigned)tochar((j >> 6) & 077);
1369 mydata[i++] = (unsigned)tochar(j & 077);
1371 case 3: /* 3 = 16-bit CRC */
1372 crc = chk3(mydata+lp,i-lp);
1373 mydata[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);
1374 mydata[i++] = (unsigned)tochar((crc >> 6) & 077);
1375 mydata[i++] = (unsigned)tochar(crc & 077);
1377 case 4: /* 2 = 12-bit chksum, blank-free */
1378 j = chk2(mydata+lp,i-lp);
1380 (unsigned)(tochar((unsigned)(((j >> 6) & 077) + 1)));
1381 mydata[i++] = (unsigned)(tochar((unsigned)((j & 077) + 1)));
1385 mydata[i++] = seol; /* End of line (packet terminator) */
1388 If TELNET connection and packet terminator is carriage return,
1389 we must stuff either LF or NUL, according to SET TELNET NEWLINE-MODE
1390 (tn_nlm), to meet the TELNET NVT specification, unless user said RAW.
1392 If NEWLINE-MODE is set to LF instead of CR, we still send CR-NUL
1393 on a NVT connection and CR on a binary connection.
1398 #endif /* STREAMING */
1399 ((network && ttnproto == NP_TELNET) || (!local && sstelnet))
1401 switch (TELOPT_ME(TELOPT_BINARY) ? tn_b_nlm : tn_nlm) {
1402 case TNL_CR: /* NVT or BINARY */
1412 #endif /* TCPSOCKET */
1413 mydata[i] = '\0'; /* Terminate string */
1417 #endif /* STREAMING */
1419 ) /* Save a function call! */
1420 logpkt('s',n,mydata,loglen); /* Log the packet */
1422 /* (PWP) add the parity quickly at the end */
1425 case 'e': /* Even */
1426 for (cp = &mydata[i-1]; cp >= mydata; cp--)
1429 case 'm': /* Mark */
1430 for (cp = &mydata[i-1]; cp >= mydata; cp--)
1434 for (cp = &mydata[i-1]; cp >= mydata; cp--)
1435 *cp = p_tbl[*cp] ^ 128;
1437 case 's': /* Space */
1438 for (cp = &mydata[i-1]; cp >= mydata; cp--)
1443 if (pktpaus) msleep(pktpaus); /* Pause if requested */
1451 #endif /* STREAMING */
1452 x = ttol(padbuf,npad); /* Send any padding */
1458 srttbl[n > 0 ? n-1 : 63] = gtimer();
1460 srttbl[n] = gtimer();
1462 #endif /* CK_TIMERS */
1463 spktl = i; /* Remember packet length */
1465 s_pkt[k].pk_len = spktl; /* also in packet info structure */
1470 This code shows (in the debug log) how long it takes write() to execute.
1471 Sometimes on a congested TCP connection, it can surprise you -- 90 seconds
1477 #endif /* STREAMING */
1481 #endif /* GFTIMER */
1486 debug(F000,"STREAMING spack skipping","",pkttyp);
1489 #endif /* STREAMING */
1490 x = ttol(mydata,spktl); /* Send the packet */
1494 #endif /* STREAMING */
1495 debug(F101,"spack spktl","",spktl);
1496 debug(F101,"spack ttol returns","",x);
1497 if (x < 0) { /* Failed. */
1498 if (local && x < -1) {
1499 xxscreen(SCR_ST,ST_ERR,0L,"FAILED: Connection lost");
1500 /* We can't send an E packet because the connection is lost. */
1501 epktsent = 1; /* So pretend we sent one. */
1502 fatalio = 1; /* Remember we got a fatal i/o error */
1504 ckstrncpy((char *)epktmsg,"Connection lost",PKTMSGLEN);
1508 if (spktl > maxsend) /* Keep track of longest packet sent */
1512 if (deblog) { /* Log elapsed time for write() */
1514 debug(F101,"spack ttol msec","",(long)((t2-t1)*1000.0));
1516 #endif /* GFTIMER */
1520 #endif /* STREAMING */
1522 sndtyp = pkttyp; /* Remember packet type for echos */
1524 if (!dontsend) { /* If really sent, */
1525 spackets++; /* count it. */
1526 flco += spktl; /* Count the characters */
1527 tlco += spktl; /* for statistics... */
1529 if (deblog) { /* Save two function calls! */
1530 dumpsbuf(); /* Dump send buffers to debug log */
1531 debug(F111,"spack calling screen, mydata=",mydata,n);
1535 #endif /* STREAMING */
1538 if (fdispla != XYFD_N) x = 1;
1539 if ((fdispla == XYFD_B) && (pkttyp == 'D' || pkttyp == 'Y')) x = 0;
1541 xxscreen(SCR_PT,pkttyp,(long)n,(char *)mydata); /* Update screen */
1543 return(spktl); /* Return length */
1546 /* C H K 1 -- Compute a type-1 Kermit 6-bit checksum. */
1549 chk1(pkt,len) register CHAR *pkt; register int len; {
1550 register unsigned int chk;
1553 register unsigned int m; /* Avoid function call */
1554 m = (parity) ? 0177 : 0377;
1555 for (chk = 0; len-- > 0; pkt++)
1559 while (len-- > 0) chk += (unsigned) *pkt++;
1560 #endif /* COMMENT */
1562 chk = chk2(pkt,len);
1563 #endif /* CKTUNING */
1564 chk = (((chk & 0300) >> 6) + chk) & 077;
1565 debug(F101,"chk1","",chk);
1569 /* C H K 2 -- Compute the numeric sum of all the bytes in the packet. */
1572 chk2(pkt,len) register CHAR *pkt; register int len; {
1575 register unsigned int m;
1576 m = (parity) ? 0177 : 0377;
1577 for (chk = 0; len-- > 0; pkt++)
1580 /* Parity has already been stripped */
1582 while (len-- > 0) chk += (unsigned) *pkt++;
1583 #endif /* COMMENT */
1584 debug(F101,"chk2","",(unsigned int) (chk & 07777));
1585 return((unsigned int) (chk & 07777));
1588 /* C H K 3 -- Compute a type-3 Kermit block check. */
1590 Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup
1591 table. Assumes the argument string contains no embedded nulls.
1595 chk3(pkt,parity,len) register CHAR *pkt; int parity; register int len; {
1596 register long c, crc;
1597 register unsigned int m;
1598 m = (parity) ? 0177 : 0377;
1599 for (crc = 0; len-- > 0; pkt++) {
1600 c = crc ^ (long)(*pkt & m);
1601 crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);
1603 return((unsigned int) (crc & 0xFFFF));
1607 chk3(pkt,len) register CHAR *pkt; register int len; {
1608 register long c, crc;
1609 for (crc = 0; len-- > 0; pkt++) {
1610 c = crc ^ (long)(*pkt);
1611 crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);
1613 debug(F101,"chk3","",(unsigned int) (crc & 0xFFFF));
1614 return((unsigned int) (crc & 0xFFFF));
1616 #endif /* COMMENT */
1618 /* N X T P K T -- Next Packet */
1620 Get packet number of next packet to send and allocate a buffer for it.
1622 0 on success, with global pktnum set to the packet number;
1623 -1 on failure to allocate buffer (fatal);
1624 -2 if resulting packet number is outside the current window.
1627 nxtpkt() { /* Called by file sender */
1630 debug(F101,"nxtpkt pktnum","",pktnum);
1631 debug(F101,"nxtpkt winlo ","",winlo);
1632 n = (pktnum + 1) % 64; /* Increment packet number mod 64 */
1633 debug(F101,"nxtpkt n","",n);
1636 x = chkwin(n,winlo,wslots); /* Don't exceed window boundary */
1637 debug(F101,"nxtpkt chkwin","",x);
1640 j = getsbuf(n); /* Get a buffer for packet n */
1642 debug(F101,"nxtpkt getsbuf failure","",j);
1646 #endif /* STREAMING */
1651 /* Functions for sending ACKs and NAKs */
1653 /* Note, we should only ACK the packet at window-low (winlo) */
1654 /* However, if an old packet arrives again (e.g. because the ACK we sent */
1655 /* earlier was lost), we ACK it again. */
1658 ack() { /* Acknowledge the current packet. */
1659 return(ackns(winlo,(CHAR *)""));
1664 fastack() { /* Acknowledge packet n */
1668 k = rseqtbl[n]; /* First find received packet n. */
1669 debug(F101,"STREAMING fastack k","",k);
1670 freesbuf(n); /* Free current send-buffer, if any */
1671 if ((j = getsbuf(n)) < 0) {
1672 /* This can happen if we have to re-ACK an old packet that has */
1673 /* already left the window. It does no harm. */
1674 debug(F101,"STREAMING fastack can't getsbuf","",n);
1677 x = spack('Y',n,0,(CHAR *)""); /* Now send it (but not really) */
1679 if (x < 0) return(x);
1680 debug(F101,"STREAMING fastack x","",x);
1682 freerbuf(k); /* don't need it any more */
1684 freesbuf(j); /* and don't need to keep ACK either */
1685 winlo = (winlo + 1) % 64;
1688 #endif /* STREAMING */
1691 ackns(n,s) int n; CHAR *s; { /* Acknowledge packet n */
1693 debug(F111,"ackns",s,n);
1695 k = rseqtbl[n]; /* First find received packet n. */
1696 debug(F101,"ackns k","",k);
1697 freesbuf(n); /* Free current send-buffer, if any */
1698 if ((j = getsbuf(n)) < 0) {
1699 /* This can happen if we have to re-ACK an old packet that has */
1700 /* already left the window. It does no harm. */
1701 debug(F101,"ackns can't getsbuf","",n);
1703 x = spack('Y',n,(int)strlen((char *)s),s); /* Now send it. */
1704 if (x < 0) return(x);
1705 debug(F101,"ackns winlo","",winlo);
1706 debug(F101,"ackns n","",n);
1707 if (n == winlo) { /* If we're acking winlo */
1709 freerbuf(k); /* don't need it any more */
1711 freesbuf(j); /* and don't need to keep ACK either */
1712 winlo = (winlo + 1) % 64;
1718 ackn(n) int n; { /* Send ACK for packet number n */
1719 return(ackns(n,(CHAR *)""));
1723 ack1(s) CHAR *s; { /* Send an ACK with data. */
1724 if (!s) s = (CHAR *)"";
1725 debug(F110,"ack1",(char *)s,0);
1726 return(ackns(winlo,s));
1729 /* N A C K -- Send a Negative ACKnowledgment. */
1731 Call with the packet number, n, to be NAK'd.
1732 Returns -1 if that packet has been NAK'd too many times, otherwise 0.
1733 Btw, it is not right to return 0 under error conditions. This is
1734 done because the -1 code is used for cancelling the file transfer.
1735 More work is needed here.
1741 if (n < 0 || n > 63) {
1742 debug(F101,"nack bad pkt num","",n);
1744 } else debug(F101,"nack","",n);
1745 if ((i = sseqtbl[n]) < 0) { /* If necessary */
1746 if (getsbuf(n) < 0) { /* get a buffer for this NAK */
1747 debug(F101,"nack can't getsbuf","",n);
1749 } else i = sseqtbl[n]; /* New slot number */
1751 if (maxtry > 0 && s_pkt[i].pk_rtr++ > maxtry) /* How many? */
1752 return(-1); /* Too many... */
1754 /* Note, don't free this buffer. Eventually an ACK will come, and that */
1755 /* will set it free. If not, well, it's back to ground zero anyway... */
1757 x = spack('N',n,0,(CHAR *) ""); /* NAKs never have data. */
1761 #ifndef NEWDPL /* This routine no longer used */
1763 * (PWP) recalculate the optimal packet length in the face of errors.
1764 * This is a modified version of the algorithm by John Chandler in Kermit/370,
1765 * see "Dynamic Packet Size Control", Kermit News, V2 #1, June 1988.
1767 * This implementation minimizes the total overhead equation, which is
1769 * Total chars = file_chars + (header_len * num_packs)
1770 * + (errors * (header_len + packet_len))
1772 * Differentiate with respect to number of chars, solve for packet_len, get:
1774 * packet_len = sqrt (file_chars * header_len / errors)
1778 (FDC) New super-simple algorithm. If there was an error in the most recent
1779 packet exchange, cut the send-packet size in half, down to a minimum of 20.
1780 If there was no error, increase the size by 5/4, up to the maximum negotiated
1781 length. Seems to be much more responsive than previous algorithm, which took
1782 forever to recover the original packet length, and it also went crazy under
1785 Here's another idea for packet length resizing that keeps a history of the
1786 last n packets. Push a 1 into the left end of an n-bit shift register if the
1787 current packet is good, otherwise push a zero. The current n-bit value, w, of
1788 this register is a weighted sum of the noise hits for the last n packets, with
1789 the most recent weighing the most. The current packet length is some function
1790 of w and the negotiated packet length, like:
1792 (2^n - w) / (2^n) * (negotiated length)
1794 If the present resizing method causes problems, think about this one a little
1803 if (numerrs == 0) return; /* bounds check just in case */
1805 /* overhead on a data packet is npad+5+bctr, plus 3 if extended packet */
1806 /* an ACK is 5+bctr */
1808 /* first set x = per packet overhead */
1809 if (wslots > 1) /* Sliding windows */
1810 x = (long) (npad+5+bctr); /* packet only, don't count ack */
1811 else /* Stop-n-wait */
1812 x = (long) (npad+5+3+bctr+5+bctr); /* count packet and ack. */
1814 /* then set x = packet length ** 2 */
1815 x = x * ( ffc / (long) numerrs); /* careful of overflow */
1817 /* calculate the long integer sqrt(x) quickly */
1822 q = (q + x/q) >> 1; /* should converge in about 4 steps */
1823 if ((q > 94) && (q < 130)) /* break-even point for long packets */
1825 if (q > spmax) q = spmax; /* maximum bounds */
1826 if (q < 10) q = 10; /* minimum bounds */
1827 spsiz = q; /* set new send packet size */
1828 debug(F101,"rcalcpsiz","",q);
1831 debug(F101,"rcalcpsiz numerrs","",numerrs);
1832 debug(F101,"rcalcpsiz spsiz","",spsiz);
1840 spsiz = (spsiz / 4) * 5;
1841 if (spsiz < 20) spsiz = 20;
1842 if (spsiz > spmax) spsiz = spmax;
1843 debug(F101,"rcalcpsiz new spsiz","",spsiz);
1845 #endif /* COMMENT */
1849 /* R E S E N D -- Retransmit packet n. */
1852 Returns 0 or positive on success (the number of retries for packet n).
1853 On failure, returns a negative number, and an error message is placed
1857 resend(n) int n; { /* Send packet n again. */
1860 CKFLOAT t1 = 0.0, t2 = 0.0;
1861 #endif /* GFTIMER */
1863 debug(F101,"resend seq","",n);
1865 k = chkwin(n,winlo,wslots); /* See if packet in current window */
1866 j = -1; /* Assume it's lost */
1867 if (k == 0) j = sseqtbl[n]; /* See if we still have a copy of it */
1868 if (k != 0 || j < 0) { /* If not.... */
1869 if (nakstate && k == 1) {
1871 Packet n is in the previous window and we are the file receiver.
1872 We already sent the ACK and deallocated its buffer so we can't just
1873 retransmit the ACK. Rather than give up, we try some tricks...
1875 if (n == 0 && spackets < 63 && myinit[0]) { /* ACK to Send-Init */
1877 If the packet number is 0, and we're at the beginning of a protocol
1878 operation (spackets < 63), then we have to resend the ACK to an I or S
1879 packet, complete with parameters in the data field. So we take a chance and
1880 send a copy of the parameters in an ACK packet with block check type 1.
1882 int bctlsav; /* Temporary storage */
1884 bctlsav = bctl; /* Save current block check length */
1885 bctusav = bctu; /* and type */
1886 bctu = bctl = 1; /* Set block check to 1 */
1887 x = spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);
1888 if (x < 0) return(x);
1889 logpkt('#',n,(CHAR *)"<reconstructed>",0); /* Log it */
1890 bctu = bctusav; /* Restore block check type */
1891 bctl = bctlsav; /* and length */
1893 } else { /* Not the first packet */
1895 It's not the first packet of the protocol operation. It's some other packet
1896 that we have already ACK'd and forgotten about. So we take a chance and
1897 send an empty ACK using the current block-check type. Usually this will
1898 work out OK (like when acking Data packets), and no great harm will be done
1899 if it was some other kind of packet (F, etc). If we are requesting an
1900 interruption of the file transfer, the flags are still set, so we'll catch
1901 up on the next packet.
1903 x = spack('Y',n,0,(CHAR *) "");
1904 if (x < 0) return(x);
1907 xxscreen(SCR_PT,'%',(long)pktnum,"Retransmission");
1911 Packet number is not in current or previous window. We seem to hit this
1912 code occasionally at the beginning of a transaction, for apparently no good
1913 reason. Let's just log it for debugging, send nothing, and try to proceed
1914 with the protocol rather than killing it.
1916 debug(F101,"resend PKT NOT IN WINDOW","",n);
1917 debug(F101,"resend k","",k);
1922 /* OK, it's in the window and it's not lost. */
1924 debug(F101,"resend pktinfo index","",k);
1926 if (maxtry > 0 && s_pkt[j].pk_rtr++ > maxtry) { /* Over retry limit */
1930 debug(F101,"resend retry","",s_pkt[j].pk_rtr); /* OK so far */
1931 dumpsbuf(); /* (debugging) */
1932 if (s_pkt[j].pk_typ == ' ') { /* Incompletely formed packet */
1933 if (nakstate) { /* (This shouldn't happen any more) */
1936 xxscreen(SCR_PT,'%',(long)pktnum,"(resend)");
1937 return(s_pkt[j].pk_rtr);
1938 } else { /* No packet to resend! */
1941 This happened (once) while sending a file with 2 window slots and typing
1942 X to the sender to cancel the file. But since we're cancelling anyway,
1943 there's no need to give a scary message.
1945 sprintf((char *)epktmsg,
1946 "resend logic error: NPS, n=%d, j=%d.",n,j);
1949 /* Just ignore it. */
1951 #endif /* COMMENT */
1956 if (deblog) t1 = gftimer();
1957 #endif /* GFTIMER */
1960 /* Everything ok, send the packet */
1963 srttbl[n] = gtimer(); /* Update the timer */
1964 #endif /* CK_TIMERS */
1965 x = ttol(s_pkt[j].pk_adr,s_pkt[j].pk_len);
1971 debug(F101,"resend ttol msec","",(long)((t2-t1)*1000.0));
1973 #endif /* GFTIMER */
1975 debug(F101,"resend ttol returns","",x);
1977 retrans++; /* Count a retransmission */
1978 xxscreen(SCR_PT,'%',(long)pktnum,"(resend)"); /* Tell user about resend */
1979 logpkt('S',n,s_pkt[j].pk_adr, s_pkt[j].pk_len); /* Log the resent packet */
1980 return(s_pkt[j].pk_rtr); /* Return the number of retries. */
1983 /* E R R P K T -- Send an Error Packet */
1986 errpkt(reason) CHAR *reason; { /* ...containing the reason given */
1987 extern int rtimo, state, justone;
1989 czseen = 1; /* Also cancels batch */
1990 state = 0; /* Reset protocol state */
1991 debug(F110,"errpkt",reason,0);
1992 tlog(F110,"Protocol Error:",(char *)reason,0L);
1993 xxscreen(SCR_EM,0,0L,reason);
1995 x = spack('E',pktnum,size,data);
1996 ckstrncpy((char *)epktmsg,(char *)reason,PKTMSGLEN);
1997 y = quiet; quiet = 1; epktsent = 1; /* Close files silently. */
2001 I just sent an E-packet. I'm in local mode, I was receiving a file,
2002 I'm not a server, and sliding windows are in use. Therefore, there are
2003 likely to be a bunch of packets already "in the pipe" on their way to me
2004 by the time the remote sender gets the E-packet. So the next time I
2005 CONNECT or try to start another protocol operation, I am likely to become
2006 terribly confused by torrents of incoming material. To prevent this,
2007 the following code soaks up packets from the connection until there is an
2008 error or timeout, without wasting too much time waiting.
2010 Exactly the same problem occurs when I am in remote mode or if I am
2011 in server mode with the justone flag set. In remote mode not only
2012 does the packet data potentially get echo'd back to the sender which
2013 is confusing to the user in CONNECT mode, but it also may result in the
2014 host performing bizarre actions such as suspending the process if ^Z is
2017 Furthermore, thousands of packets bytes in the data stream prevent the
2018 client from being able to process Telnet Kermit Option negotiations
2022 /* Because streaming sets the timeout to 0... */
2024 timint = rcvtimo = rtimo;
2027 #endif /* STREAMING */
2028 if (what & W_RECV &&
2029 (!server || (server && justone)) &&
2033 #endif /* STREAMING */
2036 CKFLOAT oldsec, sec = (CKFLOAT) 0.0;
2038 int oldsec, sec = 0;
2039 #endif /* GFTIMER */
2040 debug(F101,"errpkt draining","",wslots);
2041 xxscreen(SCR_ST,ST_MSG,0l,"Draining incoming packets, wait...");
2042 while (x > -1) { /* Don't bother if no connection */
2046 if (oldsec != (CKFLOAT) 0.0)
2047 timint = rcvtimo = (int) (sec - oldsec + 0.5);
2051 timint = rcvtimo = sec - oldsec + 1;
2052 #endif /* GFTIMER */
2054 timint = rcvtimo = 1;
2055 msleep(50); /* Allow a bit of slop */
2056 x = rpack(); /* Read a packet */
2057 if (x == 'T' || x == 'z') /* Timed out means we're done */
2059 xxscreen(SCR_PT,x,rsn,""); /* Let user know */
2061 xxscreen(SCR_ST,ST_MSG,0l,"Drain complete.");
2063 if ((x = (what & W_KERMIT)))
2064 xitsta |= x; /* Remember what failed. */
2069 /* scmd() -- Send a packet of the given type */
2073 scmd(char t, CHAR *dat)
2075 scmd(t,dat) char t; CHAR *dat;
2076 #endif /* CK_ANSIC */
2079 extern char * srimsg;
2080 debug(F000,"scmd",dat,t);
2081 if (encstr(dat) < 0) { /* Encode the command string */
2082 srimsg = "String too long";
2085 x = spack(t,pktnum,size,data);
2086 debug(F101,"scmd spack","",x);
2090 /* Compose and Send GET packet */
2092 struct opktparm { /* O-Packet item list */
2094 struct opktparm * opktnext;
2097 struct opktparm * opkthead = NULL; /* Linked list of O-packet fields */
2098 int opktcnt = 0; /* O-Packet counter */
2099 char * srimsg = NULL; /* GET-Packet error message */
2101 /* S O P K T -- Send O-Packet */
2103 Sends one O-Packet each time called, using first-fit method of filling
2104 the packet from linked list of parameters pointed to by opkthead.
2105 To be called repeatedly until list is empty or there is an error.
2108 0 on success and no more fields left to send.
2109 1 on success but with more fields left to be sent.
2114 int n = 0; /* Field number in this packet */
2115 int rc = 0; /* Return code */
2116 int len = 0; /* Data field length */
2118 struct opktparm * o = NULL;
2119 struct opktparm * t = NULL;
2120 struct opktparm * prev = NULL;
2121 CHAR * dsave = data;
2122 int x, ssave = spsiz;
2124 srimsg = NULL; /* Error message */
2125 o = opkthead; /* Point to head of list */
2126 if (!o) { /* Oops, no list... */
2127 srimsg = "GET Packet Internal Error 1";
2128 debug(F100,"sopkt NULL list","",0);
2131 while (o) { /* Go thru linked list... */
2132 c = *(o->opktitem); /* Parameter code */
2133 debug(F000,"sopkt",o->opktitem,c);
2134 x = encstr((CHAR *)o->opktitem);
2135 debug(F111,"sopkt encstr",dsave,x);
2136 if (x < 0) { /* Encode this item */
2137 if (n == 0) { /* Failure, first field in packet */
2138 debug(F100,"sopkt overflow","",0);
2139 spsiz = ssave; /* Restore these */
2141 o = opkthead; /* Free linked list */
2143 if (o->opktitem) free(o->opktitem);
2149 srimsg = "GET Packet Too Long for Server";
2150 return(-1); /* Fail */
2151 } else { /* Not first field in packet */
2152 debug(F110,"sopkt leftover",o->opktitem,0);
2153 prev = o; /* Make this one the new previous */
2154 o = o->opktnext; /* Get next */
2155 c = NUL; /* So we know we're not done */
2156 *data = NUL; /* Erase any partial encoding */
2157 continue; /* We can try this one again later */
2160 n++; /* Encoding was successful */
2161 debug(F111,"sopkt field",data,x);
2162 len += x; /* Total data field length */
2163 data += x; /* Set up for next field... */
2165 free(o->opktitem); /* Free item just encoded */
2166 if (o == opkthead) { /* If head */
2167 opkthead = o->opktnext; /* Move head to next */
2168 free((char *)o); /* Free this list node */
2170 } else { /* If not head */
2171 o = o->opktnext; /* Get next */
2172 prev->opktnext = o; /* Link previous to next */
2174 if (c == '@') /* Loop exit */
2176 if (!o && !opkthead) { /* Set up End Of Parameters Field */
2177 o = (struct opktparm *)malloc(sizeof(struct opktparm));
2180 if (!(o->opktitem = (CHAR *)malloc(3))) {
2182 srimsg = "GET Packet Internal Error 8";
2185 ckstrncpy((char *)(o->opktitem), "@ ", 3);
2186 debug(F111,"sopkt o->opktitem",o->opktitem,
2187 strlen((char *)(o->opktitem)));
2192 data = dsave; /* Restore globals */
2194 debug(F110,"sopkt data",data,0);
2195 debug(F101,"sopkt opktcnt","",opktcnt);
2196 if (opktcnt++ > 0) {
2197 if (nxtpkt() < 0) { /* Get next packet number and buffer */
2198 srimsg = "GET Packet Internal Error 9";
2202 debug(F101,"sopkt pktnum","",pktnum);
2203 rc = spack((char)'O',pktnum,len,data); /* Send O-Packet */
2204 debug(F101,"sopkt spack","",rc);
2205 if (rc < 0) /* Failed */
2206 srimsg = "Send Packet Failure"; /* Set message */
2207 else /* Succeeded */
2208 rc = (c == '@') ? 0 : 1; /* 1 = come back for more, 0 = done */
2209 debug(F101,"sopkt rc","",rc);
2213 /* S R I N I T -- Send GET packet */
2215 Sends the appropriate GET-Class packet.
2218 0 if packet sent successfully and we can move on to the next state
2219 1 if an O-packet was sent OK but more O packets still need to be sent.
2222 srinit(reget, retrieve, opkt) int reget, retrieve, opkt; {
2223 int x = 0, left = 0;
2224 extern int oopts, omode;
2227 extern int recursive;
2228 debug(F101,"srinit recursive","",recursive);
2229 #endif /* RECURSIVE */
2230 debug(F101,"srinit reget","",reget);
2231 debug(F101,"srinit retrieve","",retrieve);
2232 debug(F101,"srinit opkt","",opkt);
2233 debug(F101,"srinit oopts","",oopts);
2234 debug(F101,"srinit omode","",omode);
2235 debug(F110,"srinit cmarg",cmarg,0);
2239 if (!cmarg) cmarg = "";
2241 srimsg = "GET with no filename";
2242 debug(F100,"srinit null cmarg","",0);
2245 if (opkt) { /* Extended GET is totally different */
2247 struct opktparm * o = NULL;
2248 struct opktparm * prev = NULL;
2252 /* Build O-Packet fields and send (perhaps first) O-Packet */
2254 if (oopts > -1) { /* Write Option flags */
2255 o = (struct opktparm *)malloc(sizeof(struct opktparm));
2257 srimsg = "GET Packet Internal Error 2";
2258 debug(F100,"srinit malloc fail O1","",0);
2261 sprintf(buf,"Ox%d",oopts); /* safe */
2262 x = (int) strlen(buf+2);
2264 o->opktitem = (CHAR *)malloc(x + 3);
2266 srimsg = "GET Packet Internal Error 3";
2267 debug(F100,"srinit malloc fail O2","",0);
2270 ckstrncpy((char *)(o->opktitem),buf,x+3);
2276 if (omode > -1) { /* If Xfer Mode specified, write it */
2277 o = (struct opktparm *)malloc(sizeof(struct opktparm));
2279 srimsg = "GET Packet Internal Error 4";
2280 debug(F100,"srinit malloc fail M1","",0);
2283 sprintf(buf,"Mx%d",omode); /* safe */
2284 x = (int) strlen(buf+2);
2286 o->opktitem = (CHAR *)malloc(x + 3);
2288 srimsg = "GET Packet Internal Error 5";
2289 debug(F100,"srinit malloc fail O2","",0);
2292 ckstrncpy((char *)(o->opktitem),buf,x+3);
2301 /* Same deal for oname and opath eventually but not needed now... */
2303 x = strlen(cmarg); /* Now do filename */
2304 if (x > spsiz - 4) {
2305 srimsg = "GET Packet Too Long for Server";
2308 o = (struct opktparm *)malloc(sizeof(struct opktparm));
2310 srimsg = "GET Packet Internal Error 6";
2311 debug(F100,"srinit malloc fail F1","",0);
2315 o->opktitem = (CHAR *)malloc(left + 1);
2317 srimsg = "GET Packet Internal Error 7";
2318 debug(F100,"srinit malloc fail F2","",0);
2324 if (x > 94) { /* Too long for normal length */
2325 *p++ = SYN; /* Escape length with Ctrl-V */
2326 *p++ = tochar(x / 95);
2327 *p++ = tochar(x % 95);
2329 } else { /* Normal encoding for 94 or less */
2333 ckstrncpy((char *)p,cmarg,left); /* Copy the filename */
2341 /* End of Parameters */
2343 prev->opktnext = NULL; /* End of list. */
2347 /* Not Extended GET */
2349 if (encstr((CHAR *)cmarg) < 0) { /* Encode the filename. */
2350 srimsg = "GET Packet Too Long for Server";
2353 if (retrieve) { /* Send the packet. */
2356 x = spack((char)'W',pktnum,size,data); /* GET /DELETE /RECURSIVE */
2358 #endif /* RECURSIVE */
2359 x = spack((char)'H',pktnum,size,data); /* GET /DELETE */
2363 x = spack((char)'V',pktnum,size,data); /* GET /RECURSIVE */
2364 #endif /* RECURSIVE */
2366 x = spack((char)(reget ? 'J' : 'R'),pktnum,size,data); /* GET */
2368 srimsg = "Send Packet Failure";
2369 return(x < 0 ? x : 0);
2373 /* K S T A R T -- Checks for a Kermit packet while in terminal mode. */
2375 /* (or command mode...) */
2383 #endif /* CK_ANSIC */
2385 static CHAR * p = NULL;
2388 static CHAR * pk = NULL;
2390 ch &= 0177; /* Strip 8th bit */
2392 /* Because we're in cooked mode at the command prompt... */
2395 debug(F110,"kstart","ch == LF",0);
2396 if ((what == W_COMMAND || what == W_INIT || what == W_NOTHING)) {
2399 debug(F110,"kstart","ch = CR",0);
2405 if (adl_kmode == ADL_STR) {
2415 debug(F100, "kstart Kermit Start String","",0);
2416 return(PROTO_K + 1);
2423 if (ch == stchr) { /* Start of packet */
2427 debug(F101,"kstart SOP","",ch);
2428 } else if (ch == eol) { /* End of packet */
2431 debug(F101,"kstart EOL","",ch);
2433 if (p - ksbuf < 94 ) {
2437 rc = chkspkt((char *)ksbuf);
2438 debug(F111,"kstart EOP chkspkt", ksbuf, rc);
2441 if (rc == 2) rc = -1;
2442 debug(F111,"kstart ksbuf",ksbuf,rc);
2445 debug(F110,"kstart","p - ksbuf >= 94",0);
2453 if (p - ksbuf < 94) {
2457 debug(F110,"kstart","p - ksbuf >= 94",0);
2465 /* Z S T A R T -- Checks for a ZMODEM packet while in terminal mode. */
2472 #endif /* CK_ANSIC */
2474 static CHAR * matchstr = (CHAR *) "\030B00";
2475 /* "rz\r**\030B00000000000000\r\033J\021"; */
2476 static CHAR * p = NULL;
2477 extern int inserver;
2486 p = adl_zmode == ADL_PACK ? matchstr : adl_zstr;
2495 if (adl_zmode == ADL_PACK) {
2497 debug(F100, "zstart Zmodem SOP","",0);
2500 debug(F100, "zstart Zmodem Start String","",0);
2504 debug(F100, "zstart Zmodem SOP","",0);
2506 return(PROTO_Z + 1);
2510 p = adl_zmode == ADL_PACK ? matchstr : adl_zstr;
2521 /* A U T O D O W N */
2528 autodown(ch) int ch;
2529 #endif /* CK_ANSIC */
2532 /* The Kermit and Zmodem Auto-download calls go here */
2534 extern int justone; /* From protocol module */
2535 extern int debses, protocol, apcactive, autodl, inautodl;
2537 extern char *apcbuf;
2539 extern char apcbuf[];
2540 #endif /* DCMDBUF */
2542 extern int apclength, term_io;
2546 if ((autodl || inautodl
2548 || TELOPT_SB(TELOPT_KERMIT).kermit.me_start
2549 #endif /* IKS_OPTION */
2556 #endif /* XYZ_INTERNAL */
2557 if (p_avail && zstart((CHAR) ch)) {
2558 debug(F100, "Zmodem download","",0);
2561 apc_command(APC_LOCAL,"receive /protocol:zmodem");
2564 ckstrncpy(apcbuf,"receive /protocol:zmodem",APCBUFLEN);
2565 apcactive = APC_LOCAL;
2572 k = kstart((CHAR) ch);
2576 #else /* NOSERVER */
2578 #endif /* NOSERVER */
2579 ) { /* We saw a valid S or I packet */
2580 if (k < 0) { /* Stuff RECEIVE into APC buffer */
2586 "set proto kermit, server, set protocol g",
2592 "set proto kermit,server,set proto xmodem",
2598 "set proto kermit,server,set proto xmodem-crc",
2604 "set proto kermit,server, set protocol y",
2610 "set proto kermit,server,set proto zmodem",
2616 ckstrncpy(apcbuf,"server",APCBUFLEN);
2621 ckstrncpy(apcbuf,"receive /protocol:kermit",APCBUFLEN);
2625 apc_command(APC_LOCAL,apcbuf);
2628 ckstrncpy(apcbuf,"receive /protocol:zmodem",APCBUFLEN);
2629 apcactive = APC_LOCAL;
2638 /* C H K S P K T -- Check if buf contains a valid S or I packet */
2641 chkspkt(buf) char *buf; {
2648 if (!buf) return(0);
2649 buflen = strlen(buf);
2650 if (buflen < 5) return(0); /* Too short */
2651 if (*s++ != stchr) return(0); /* SOH */
2652 len = xunchar(*s++); /* Length */
2653 if (len < 0) return(0);
2654 if (*s++ != SP) return(0); /* Sequence number */
2655 type = *s++; /* Type */
2656 if (type != 'S' && type != 'I')
2658 if (buflen < len + 2) return(0);
2659 s += (len - 3); /* Position of checksum */
2660 chk = (CHAR) (*s); /* Checksum */
2662 if (xunchar(chk) != chk1((CHAR *)(buf+1),buflen-2)) /* Check it */
2665 return(type == 'S' ? 1 : 2);
2667 #endif /* CK_AUTODL */
2669 /* R P A C K -- Read a Packet */
2672 rpack reads a packet and returns the packet type, or else Q if the
2673 packet was invalid, or T if a timeout occurred. Upon successful return,
2674 sets the values of global rsn (received sequence number), rln (received
2675 data length), and rdatap (pointer to null-terminated data field), and
2676 returns the packet type. NOTE: This is an inner-loop function so must be
2677 efficient. Protect function calls by if-tests where possible, e.g.
2678 "if (pktlog) logpkt(...);".
2682 register int i, j, x, lp; /* Local variables */
2685 #endif /* CKTUNING */
2686 int k, type, chklen;
2688 CHAR pbc[5]; /* Packet block check */
2689 CHAR *sohp; /* Pointer to SOH */
2690 CHAR e; /* Packet end character */
2693 CKFLOAT t1 = 0.0, t2 = 0.0;
2694 #endif /* GFTIMER */
2696 debug(F101,"rpack pktnum","",pktnum);
2699 if (chkint() < 0) /* Check for console interrupts. */
2701 #endif /* OLDCHKINT */
2703 k = getrbuf(); /* Get a new packet input buffer. */
2704 debug(F101,"rpack getrbuf","",k);
2705 if (k < 0) { /* Return like this if none free. */
2708 recpkt = r_pkt[k].bf_adr;
2709 *recpkt = '\0'; /* Clear receive buffer. */
2710 sohp = recpkt; /* Initialize pointers to it. */
2712 rsn = rln = -1; /* In case of failure. */
2713 e = (turn) ? turnch : eol; /* Use any handshake char for eol */
2715 /* Try to get a "line". */
2718 debug(F110,"rpack ksbuf",ksbuf,0);
2719 if (ksbuf[0]) { /* Kermit packet already */
2720 int x; /* collected for us in CONNECT mode */
2721 CHAR *s1 = recpkt, *s2 = ksbuf;
2723 while (*s2) { /* Copy and get length */
2724 *s1++ = *s2++; /* No point optimizing this since */
2725 j++; /* it's never more than ~20 chars */
2729 x = parchk(recpkt, stchr, j); /* Check parity */
2730 debug(F000,"autodownload parity","",parity);
2731 debug(F000,"autodownload parchk","",x);
2732 if (x > -1 && parity != x) {
2736 #endif /* PARSENSE */
2737 ksbuf[0] = NUL; /* Don't do this next time! */
2739 } else { /* Normally go read a packet */
2740 #endif /* CK_AUTODL */
2744 debug(F101,"rpack timint","",timint);
2745 debug(F101,"rpack rcvtimo","",rcvtimo);
2747 debug(F101,"rpack streaming","",streaming);
2748 #endif /* STREAMING */
2750 /* Measure how long it takes to read a packet */
2752 #endif /* GFTIMER */
2756 /* JUST IN CASE (otherwise this could clobber streaming) */
2761 #endif /* STREAMING */
2762 ) && (rcvtimo != 0)) {
2763 debug(F101,"rpack timint 0 || streaming but rcvtimo","",rcvtimo);
2770 So far the final turn argument is only for ck[uvdl]tio.c. Should be added
2771 to the others too. (turn == handshake character.)
2773 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
2776 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
2779 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
2782 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
2785 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
2788 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);
2790 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr);
2793 #endif /* STRATUS */
2794 #endif /* datageneral */
2797 if (parity != 0 && parity != 's' && ttprty != 0) {
2798 if (parity != ttprty) autopar = 1;
2801 #else /* !PARSENSE */
2802 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e);
2803 #endif /* PARSENSE */
2807 debug(F101,"rpack ttinl len","",j);
2810 debug(F101,"rpack ttinl msec","",(long)((t2-t1)*1000.0));
2811 #endif /* GFTIMER */
2816 if (streaming && sndtyp == 'D' && j == 0)
2818 #endif /* STREAMING */
2821 /* -1 == timeout, -2 == ^C, -3 == connection lost or fatal i/o */
2822 debug(F101,"rpack: ttinl fails","",j); /* Otherwise, */
2823 freerbuf(k); /* Free this buffer */
2824 if (j < -1) { /* Bail out if ^C^C typed. */
2827 debug(F101,"rpack ^C server","",server);
2828 debug(F101,"rpack ^C en_fin","",en_fin);
2829 } else if (j == -3) {
2831 debug(F101,"rpack fatalio","",en_fin);
2835 if (nakstate) /* j == -1 is a read timeout */
2836 xxscreen(SCR_PT,'T',(long)winlo,"");
2838 xxscreen(SCR_PT,'T',(long)pktnum,"");
2839 logpkt('r',-1,(CHAR *)"<timeout>",0);
2840 if (flow == 1) ttoc(XON); /* In case of Xoff blockage. */
2845 #endif /* CK_AUTODL */
2848 tlci += j; /* All OK, Count the characters. */
2851 /* Find start of packet */
2854 for (i = 0; (recpkt[i] != stchr) && (i < j); i++)
2855 sohp++; /* Find mark */
2856 if (i++ >= j) { /* Didn't find it. */
2857 logpkt('r',-1,"<timeout>",0);
2862 i = 1; /* ttinl does this for us */
2863 #endif /* PARSENSE */
2865 rpackets++; /* Count received packet. */
2866 lp = i; /* Remember LEN position. */
2867 if ((j = xunchar(recpkt[i++])) == 0) { /* Get packet length. */
2868 if ((j = lp+5) > MAXRP) { /* Long packet */
2869 return('Q'); /* Too long */
2873 /* Save some function-call and loop overhead... */
2875 /* ttinl() already removed parity */
2877 #endif /* COMMENT */
2878 chk = (unsigned) ((unsigned) recpkt[i-1] +
2879 (unsigned) recpkt[i] +
2880 (unsigned) recpkt[i+1] +
2881 (unsigned) recpkt[i+2] +
2882 (unsigned) recpkt[i+3]
2886 chk = (unsigned) ((unsigned) (recpkt[i-1] & 077) +
2887 (unsigned) (recpkt[i] & 077) +
2888 (unsigned) (recpkt[i+1] & 077) +
2889 (unsigned) (recpkt[i+2] & 077) +
2890 (unsigned) (recpkt[i+3] & 077)
2892 #endif /* COMMENT */
2893 if (xunchar(recpkt[j]) != ((((chk & 0300) >> 6) + chk) & 077))
2895 x = recpkt[j]; /* Header checksum. */
2896 recpkt[j] = '\0'; /* Calculate & compare. */
2897 if (xunchar(x) != chk1(recpkt+lp,5))
2898 #endif /* CKTUNING */
2901 logpkt('r',-1,(CHAR *)"<crunched:hdr>",0);
2902 xxscreen(SCR_PT,'%',(long)pktnum,"Bad packet header");
2906 recpkt[j] = x; /* Checksum ok, put it back. */
2907 #endif /* CKTUNING */
2908 rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctl;
2909 j = 3; /* Data offset. */
2911 debug(F101,"rpack packet length less than 3","",j);
2913 logpkt('r',-1,(CHAR *)"<crunched:len>",0);
2914 xxscreen(SCR_PT,'%',(long)pktnum,"Bad packet length");
2917 rln = j - bctl - 2; /* Regular packet */
2918 j = 0; /* No extended header */
2920 rsn = xunchar(recpkt[i++]); /* Sequence number */
2921 if (pktlog) /* Save a function call! */
2922 logpkt('r',rsn,sohp,rln+bctl+j+4);
2923 if (rsn < 0 || rsn > 63) {
2924 debug(F101,"rpack bad sequence number","",rsn);
2927 logpkt('r',rsn,(CHAR *)"<crunched:seq>",0);
2928 xxscreen(SCR_PT,'%',(long)pktnum,"Bad sequence number");
2932 If this packet has the same type as the packet just sent, assume it is
2933 an echo and ignore it. Don't even bother with the block check calculation:
2934 even if the packet is corrupted, we don't want to NAK an echoed packet.
2935 Nor must we NAK an ACK or NAK.
2937 type = recpkt[i++]; /* Get packet's TYPE field */
2938 if (type == sndtyp || (nakstate && (type == 'N' /* || type == 'Y' */ ))) {
2939 debug(F000,"rpack echo","",type); /* If it's an echo */
2940 freerbuf(k); /* Free this buffer */
2941 logpkt('#',rsn,(CHAR *)"<echo:ignored>",0);
2942 return('e'); /* Return special (lowercase) code */
2945 Separate the data from the block check, accounting for the case where
2946 a packet was retransmitted after the block check switched.
2948 if (type == 'I' || type == 'S') { /* I & S packets always have type 1 */
2950 rln = rln + bctl - 1;
2951 } else if (type == 'N') { /* A NAK packet never has data */
2952 chklen = xunchar(recpkt[lp]) - 2;
2953 rln = rln + bctl - chklen;
2954 } else chklen = bctl;
2956 if (deblog) { /* Save 2 function calls */
2957 debug(F101,"rpack bctl","",bctl);
2958 debug(F101,"rpack chklen","",chklen);
2961 i += j; /* Buffer index of DATA field */
2962 rdatap = recpkt+i; /* Pointer to DATA field */
2963 if ((j = rln + i) > r_pkt[k].bf_len) { /* Make sure it fits */
2964 debug(F101,"packet too long","",j);
2966 logpkt('r',rsn,(CHAR *)"<overflow>",0);
2969 for (x = 0; x < chklen; x++) /* Copy the block check */
2970 pbc[x] = recpkt[j+x]; /* 3 bytes at most. */
2971 pbc[x] = '\0'; /* Null-terminate block check string */
2972 recpkt[j] = '\0'; /* and the packet Data field. */
2974 if (chklen == 2 && bctu == 4) { /* Adjust for Blank-Free-2 */
2975 chklen = 4; /* (chklen is now a misnomer...) */
2976 debug(F100,"rpack block check B","",0);
2978 switch (chklen) { /* Check the block check */
2979 case 1: /* Type 1, 6-bit checksum */
2980 if (xunchar(*pbc) != chk1(recpkt+lp,j-lp)) {
2983 debug(F110,"checked chars",recpkt+lp,0);
2984 debug(F101,"block check (1)","",(int) xunchar(*pbc));
2985 debug(F101,"should be (1)","",chk1(recpkt+lp,j-lp));
2989 logpkt('r',-1,(CHAR *)"<crunched:chk1>",0);
2990 xxscreen(SCR_PT,'%',(long)pktnum,"Checksum error");
2994 case 2: /* Type 2, 12-bit checksum */
2995 x = xunchar(*pbc) << 6 | xunchar(pbc[1]);
2996 if (x != chk2(recpkt+lp,j-lp)) { /* No match */
2997 if (type == 'E') { /* Allow E packets to have type 1 */
2998 recpkt[j++] = pbc[0];
3000 if (xunchar(pbc[1]) == chk1(recpkt+lp,j-lp))
3007 debug(F110,"checked chars",recpkt+lp,0);
3008 debug(F101,"block check (2)","", x);
3009 debug(F101,"should be (2)","", (int) chk2(recpkt+lp,j-lp));
3013 logpkt('r',-1,(CHAR *)"<crunched:chk2>",0);
3014 xxscreen(SCR_PT,'%',(long)pktnum,"Checksum error");
3018 case 3: /* Type 3, 16-bit CRC */
3019 crc = (xunchar(pbc[0]) << 12)
3020 | (xunchar(pbc[1]) << 6)
3021 | (xunchar(pbc[2]));
3022 if (crc != chk3(recpkt+lp,j-lp)) {
3023 if (type == 'E') { /* Allow E packets to have type 1 */
3024 recpkt[j++] = pbc[0];
3025 recpkt[j++] = pbc[1];
3027 if (xunchar(pbc[2]) == chk1(recpkt+lp,j-lp))
3029 else { j -=2; recpkt[j] = '\0'; }
3033 debug(F110,"checked chars",recpkt+lp,0);
3034 debug(F101,"block check (3)","",crc);
3035 debug(F101,"should be (3)","",(int) chk3(recpkt+lp,j-lp));
3039 logpkt('r',-1,(CHAR *)"<crunched:chk3>",0);
3040 xxscreen(SCR_PT,'%',(long)pktnum,"CRC error");
3044 case 4: /* Type 4 = Type 2, no blanks. */
3045 x = (unsigned)((xunchar(*pbc) - 1) << 6) |
3046 (unsigned)(xunchar(pbc[1]) - 1);
3047 if (x != chk2(recpkt+lp,j-lp)) {
3048 if (type == 'E') { /* Allow E packets to have type 1 */
3049 recpkt[j++] = pbc[0];
3051 if (xunchar(pbc[1]) == chk1(recpkt+lp,j-lp))
3056 debug(F101,"bad type B block check","",x);
3058 logpkt('r',-1,(CHAR *)"<crunched:chkb>",0);
3059 xxscreen(SCR_PT,'%',(long)pktnum,"Checksum error");
3063 default: /* Shouldn't happen... */
3065 logpkt('r',-1,(CHAR *)"<crunched:chkx>",0);
3066 xxscreen(SCR_PT,'%',(long)pktnum,"(crunched)");
3069 debug(F101,"rpack block check OK","",rsn);
3071 /* Now we can believe the sequence number, and other fields. */
3072 /* Here we violate strict principles of layering, etc, and look at the */
3073 /* packet sequence number. If there's already a packet with the same */
3074 /* number in the window, we remove this one so that the window will not */
3077 if ((x = rseqtbl[rsn]) != -1) { /* Already a packet with this number */
3078 retrans++; /* Count it for statistics */
3079 debug(F101,"rpack got dup","",rsn);
3080 logpkt('r',rsn,(CHAR *)"<duplicate>",0);
3081 freerbuf(x); /* Free old buffer, keep new packet. */
3082 r_pkt[k].pk_rtr++; /* Count this as a retransmission. */
3085 /* New packet, not seen before, enter it into the receive window. */
3089 rrttbl[rsn] = gtimer(); /* Timestamp */
3090 #endif /* CK_TIMERS */
3092 rseqtbl[rsn] = k; /* Make back pointer */
3093 r_pkt[k].pk_seq = rsn; /* Record in packet info structure */
3094 r_pkt[k].pk_typ = type; /* Sequence, type,... */
3095 r_pkt[k].pk_adr = rdatap; /* pointer to data buffer */
3096 if (local) { /* Save a function call! */
3098 if (fdispla != XYFD_N) x = 1;
3099 if (fdispla == XYFD_B && (type == 'D' || sndtyp == 'D')) x = 0;
3100 if (x) /* Update screen */
3101 xxscreen(SCR_PT,(char)type,(long)rsn,(char *)sohp);
3103 return(type); /* Return packet type */
3106 /* L O G P K T -- Log packet number n, pointed to by s. */
3108 /* c = 's' (send) or 'r' (receive) */
3112 logpkt(char c,int n, CHAR *s, int len)
3114 logpkt(c,n,s,len) char c; int n; CHAR *s; int len;
3115 #endif /* CK_ANSIC */
3118 if (!s) s = (CHAR *)"";
3119 if (pktlog) if (chkfn(ZPFILE) > 0) {
3120 if (n < 0) /* Construct entry header */
3121 sprintf(plog,"%c-xx-%02d-",c,(gtimer()%60)); /* safe */
3123 sprintf(plog,"%c-%02d-%02d-",c,n,(gtimer()%60)); /* safe */
3124 if (zsoutx(ZPFILE,plog,(int)strlen(plog)) < 0) {
3129 len = strlen((char *)s);
3131 char * p; /* Make SOP printable */
3132 int x; /* so we can look at logs without */
3133 p = dbchr(*s); /* triggering autodownload. */
3134 x = strlen(dbchr(*s));
3135 if (*s < 32 || (*s > 127 && *s < 160)) {
3136 if (zsoutx(ZPFILE,p,x) < 0) {
3145 if (zsoutx(ZPFILE,(char *)s,len) < 0) {
3148 } else if (zsoutx(ZPFILE,
3164 #endif /* datageneral */
3173 /* T S T A T S -- Record statistics in transaction log */
3179 CKFLOAT xx; /* Elapsed time divisor */
3180 #endif /* GFTIMER */
3182 debug(F101,"tstats xfsecs","",xfsecs);
3183 debug(F101,"tstats filcnt","",filcnt);
3184 if (filcnt == 1) { /* Get timing for statistics */
3185 tsecs = xfsecs; /* Single file, we already have it */
3187 debug(F101,"tstats fpxfsecs","",(int)fpxfsecs);
3189 #endif /* GFTIMER */
3190 } else { /* Multiple files */
3191 tsecs = gtimer(); /* Get current time */
3193 fptsecs = gftimer();
3194 #endif /* GFTIMER */
3197 if (fptsecs <= GFMINTIME) /* Calculate CPS */
3198 fptsecs = (CKFLOAT) GFMINTIME;
3199 debug(F101,"tstats fptsecs","",(int)fptsecs);
3200 xx = (CKFLOAT) tfc / fptsecs;
3201 if (sizeof(long) <= 4) { /* doesn't account for 16-bit longs */
3202 if (xx > 2147483647.0)
3203 tfcps = 2147483647L; /* 31 bits */
3211 debug(F101,"tstats tsecs","",tsecs);
3212 tfcps = tfc / tsecs;
3213 #endif /* GFTIMER */
3215 ztime(&tp); /* Get time stamp */
3216 tlog(F100,"","",0L); /* Leave a blank line */
3217 tlog(F110,"Transaction complete",tp,0L); /* Record it */
3219 if (filcnt < 1) return; /* If no files, done. */
3221 /* If multiple files, record character totals for all files */
3224 tlog(F101," files transferred ","",filcnt - filrej);
3225 tlog(F101," total file characters ","",tfc);
3226 tlog(F101," communication line in ","",tlci);
3227 tlog(F101," communication line out ","",tlco);
3230 /* Record timing info for one or more files */
3233 if (filcnt - filrej == 1) {
3234 tlog(F101," elapsed time (seconds) ","",(long) fpxfsecs);
3235 tlog(F101," effective data rate ","",filcps);
3237 tlog(F101," elapsed time (seconds) ","",(long) fptsecs);
3238 tlog(F101," effective data rate ","",(long) xx);
3241 tlog(F101," elapsed time (seconds) ","",(long) tsecs);
3244 lx = (tfc * 10L) / (long) tsecs;
3245 tlog(F101," effective data rate ","",lx/10L);
3247 #endif /* GFTIMER */
3248 tlog(F100,"","",0L); /* Leave a blank line */
3251 /* F S T A T S -- Record file statistics in transaction log */
3257 fpxfsecs = gftimer() - fpfsecs;
3258 if (fpxfsecs <= GFMINTIME)
3259 fpxfsecs = (CKFLOAT) GFMINTIME;
3260 xx = (CKFLOAT) ffc / fpxfsecs;
3261 if (sizeof(long) <= 4) {
3262 if (xx > 2147483647.0)
3263 tfcps = 2147483647L; /* 31 bits */
3268 if (sizeof(int) >= 4)
3269 xfsecs = (int) fpxfsecs;
3270 else if (fpxfsecs < 32768.0)
3271 xfsecs = (int) fpxfsecs;
3275 xfsecs = gtimer() - fsecs;
3276 if (xfsecs < 1L) xfsecs = 1L;
3277 filcps = ffc / xfsecs;
3278 #endif /* GFTIMER */
3286 debug(F101,"fstats tfc","",tfc);
3287 debug(F101,"fstats what","",what);
3288 debug(F110,"fstats epktmsg",epktmsg,0);
3292 if (!discard && !cxseen && !czseen && what != W_NOTHING && !*epktmsg)
3293 tlog(F101," complete, size","",ffc);