⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ckcfn2.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	    crc = chk3(mydata+lp);	    mydata[i++] = (unsigned)tochar(((crc & 0170000)) >> 12);	    mydata[i++] = (unsigned)tochar((crc >> 6) & 077);	    mydata[i++] = (unsigned)tochar(crc & 077);	    break;	case 4:				/* 2 = 12-bit chksum, blank-free */	    j = chk2(mydata+lp);		    mydata[i++] =	      (unsigned)(tochar((unsigned)(((j >> 6) & 077) + 1)));   	    mydata[i++] = (unsigned)(tochar((unsigned)((j & 077) + 1)));	    break;    }    mydata[i++] = seol;			/* End of line (packet terminator) */#ifdef TCPSOCKET/*  If TELNET connection and packet terminator is carriage return,  we must stuff either LF or NUL, according to SET TELNET NEWLINE-MODE  (tn_nlm), to meet the TELNET specification.*/    if (network && ttnproto == NP_TELNET && seol == CR)      mydata[i++] = tn_nlm ? LF : NUL;#endif /* TCPSOCKET */    mydata[i] = '\0';			/* Terminate string */    logpkt('s',n,mydata);		/* Log packet */    /* (PWP) add the parity quickly at the end */    switch (parity) {      case 'e':				/* Even */	for (cp = &mydata[i-1]; cp >= mydata; cp--)	  *cp = partab[*cp];	break;      case 'm':				/* Mark */	for (cp = &mydata[i-1]; cp >= mydata; cp--)	  *cp |= 128;	break;      case 'o':				/* Odd */	for (cp = &mydata[i-1]; cp >= mydata; cp--)	  *cp = partab[*cp] ^ 128;	break;      case 's':				/* Space */	for (cp = &mydata[i-1]; cp >= mydata; cp--)	  *cp &= 127;	break;    }    if (npad) ttol(padbuf,npad);	/* Send any padding */    spktl = i;				/* Remember packet length */    s_pkt[k].pk_len = spktl;		/* also in packet info structure */    if (ttol(mydata,spktl) < 0) return(-1); /* Send the packet */    sndtyp = pkttyp;			/* Remember packet type for echos */    spackets++;				/* Count it. */    flco += spktl;			/* Count the characters */    tlco += spktl;			/* for statistics... */    dumpsbuf();				/* Dump send buffers to debug log */    screen(SCR_PT,pkttyp,(long)n,(char *)mydata); /* Update screen */    return(spktl);			/* Return length */}/*  C H K 1  --  Compute a type-1 Kermit 6-bit checksum.  */intchk1(pkt) register CHAR *pkt; {    register unsigned int chk;    chk = chk2(pkt);    chk = (((chk & 0300) >> 6) + chk) & 077;    return((int) chk);}/*  C H K 2  --  Compute the numeric sum of all the bytes in the packet.  */unsigned intchk2(pkt) register CHAR *pkt; {    register long chk; register unsigned int m;    m = (parity) ? 0177 : 0377;    for (chk = 0; *pkt != '\0'; pkt++)      chk += *pkt & m;    return((unsigned int) (chk & 07777));}/*  C H K 3  --  Compute a type-3 Kermit block check.  *//* Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup  table.  Assumes the argument string contains no embedded nulls.*/unsigned intchk3(pkt) register CHAR *pkt; {    register long c, crc;    register unsigned int m;    m = (parity) ? 0177 : 0377;    for (crc = 0; *pkt != '\0'; pkt++) {	c = crc ^ (long)(*pkt & m);	crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]);    }    return((unsigned int) (crc & 0xFFFF));}intnxtpkt() {				/* Called by file sender */    int j, n;    debug(F101,"nxtpkt pktnum","",pktnum);    debug(F101,"nxtpkt winlo ","",winlo);    n = (pktnum + 1) % 64;		/* Increment packet number mod 64 */#ifdef COMMENT /*  Suggested by Alan Grieg.  A packet can be sent out of window in   circumstances involving acks received out of order, ...  Have to think  about this...*/    if (chkwin(n,winlo,wslots)) {	debug(F101,"nxtpkt n not in window","",n);	return(-1);    }#endif    j = getsbuf(n);			/* Get a buffer for packet n */    if (j < 0) {	debug(F101,"nxtpkt can't getsbuf","",j);	return(-1);    }    pktnum = n;	          debug(F101,"nxtpkt bumped pktnum to","",pktnum);    return(0);}/* Functions for sending ACKs and NAKs *//* Note, we should only ACK the packet at window-low (winlo) *//* However, if an old packet arrives again (e.g. because the ACK we sent *//* earlier was lost), we ACK it again. */intack() {					/* Acknowledge the current packet. */    return(ackns(winlo,(CHAR *)""));}intackns(n,s) int n; CHAR *s; {		/* Acknowledge packet n */    int j, k;    debug(F111,"ackns",s,n);    k = rseqtbl[n];			/* First find received packet n. */    debug(F101,"ackns k","",k);#ifdef COMMENT/* No need to set ACK'd bit, because we're gonna free the buffer now */    if (k > -1)				/* If in window */      s_pkt[k].pk_flg++;		/* mark the ack'd bit. */    else      debug(F101,"ackns can't set ack'd bit","",k);#endif    freesbuf(n);			/* Free current send-buffer, if any */    if ((j = getsbuf(n)) < 0) {	/* This can happen if we have to re-ACK an old packet that has */        /* already left the window.  It does no harm. */	debug(F101,"ackns can't getsbuf","",n);    }    spack('Y',n,(int)strlen((char *)s),s); /* Now send it. */    debug(F101,"ackns winlo","",winlo);    debug(F101,"ackns n","",n);    if (n == winlo) {			/* If we're acking winlo */	if (k > -1)	  freerbuf(k);			/* don't need it any more */	if (j > -1)	  freesbuf(j);			/* and don't need to keep ACK either */	winlo = (winlo + 1) % 64;    }    return(0);}intackn(n) int n; {			/* Send ACK for packet number n */    return(ackns(n,(CHAR *)""));}intack1(s) CHAR *s; {			/* Send an ACK with data. */    debug(F110,"ack1",(char *) s,0);    return(ackns(winlo, s));}/* N A C K  --   Send a Negative ACKnowledgment. *//* Call with the packet number, n, to be NAK'd. Returns -1 if that packet has been NAK'd too many times, otherwise 0. Btw, it is not right to return 0 under error conditions.  This is done because the -1 code is used for cancelling the file transfer. More work is needed here.*/intnack(n) int n; {    int i;    if (n < 0 || n > 63) {	debug(F101,"nack bad pkt num","",n);	return(0);    } else debug(F101,"nack","",n);    if ((i = sseqtbl[n]) < 0) {		/* If necessary */	if (getsbuf(n) < 0) {		/* get a buffer for this NAK */	    debug(F101,"nack can't getsbuf","",n);	    return(0);	} else i = sseqtbl[n];		/* New slot number */    }    if (s_pkt[i].pk_rtr++ > maxtry)	/* How many times have we done this? */      return(-1);			/* Too many... *//* Note, don't free this buffer.  Eventually an ACK will come, and that *//* will set it free.  If not, well, it's back to ground zero anyway...  */    spack('N',n,0,(CHAR *) "");		/* NAKs never have data. */    return(0);}/* * (PWP) recalculate the optimal packet length in the face of errors. * This is a modified version of the algorithm by John Chandler in Kermit/370,  * see "Dynamic Packet Size Control", Kermit News, V2 #1, June 1988. * * This implementation minimizes the total overhead equation, which is * *   Total chars = file_chars + (header_len * num_packs) *                            + (errors * (header_len + packet_len)) * * Differentiate with respect to number of chars, solve for packet_len, get: * *   packet_len = sqrt (file_chars * header_len / errors) *//* (FDC) New super-simple algorithm.  If there was an error in the most recent packet exchange, cut the send-packet size in half, down to a minimum of 20. If there was no error, increase the size by 5/4, up to the maximum negotiated length.  Seems to be much more responsive than previous algorithm, which took forever to recover the original packet length, and it also went crazy under certain conditions. Here's another idea for packet length resizing that keeps a history of the last n packets.  Push a 1 into the left end of an n-bit shift register if the current packet is good, otherwise push a zero.  The current n-bit value, w, of this register is a weighted sum of the noise hits for the last n packets, with the most recent weighing the most.  The current packet length is some function of w and the negotiated packet length, like:   (2^n - w) / (2^n) * (negotiated length) If the present resizing method causes problems, think about this one a little more.*/VOIDrcalcpsz() {#ifdef COMMENT/* Old way */    register long x, q;    if (numerrs == 0) return;	/* bounds check just in case */    /* overhead on a data packet is npad+5+bctr, plus 3 if extended packet */    /* an ACK is 5+bctr */    /* first set x = per packet overhead */    if (wslots > 1)	x = (long) (npad+5+bctr);    /* only the packet, don't count the ack */    else	x = (long) (npad+5+3+bctr+5+bctr);    /* then set x = packet length ** 2 */    x = x * ( ffc / (long) numerrs);	/* careful of overflow */        /* calculate the long integer sqrt(x) quickly */    q = 500;    q = (q + x/q) >> 1;    q = (q + x/q) >> 1;    q = (q + x/q) >> 1;    q = (q + x/q) >> 1;		/* should converge in about 4 steps */    if ((q > 94) && (q < 130))	/* break-even point for long packets */	q = 94;    if (q > spmax) q = spmax;	/* maximum bounds */    if (q < 10) q = 10;		/* minimum bounds */    spsiz = q;			/* set new send packet size */    debug(F101,"rcalcpsiz","",q);#else/* New way */    if (spackets < 3) return;    debug(F101,"rcalcpsiz numerrs","",numerrs);    debug(F101,"rcalcpsiz spsiz","",spsiz);    if (numerrs)      spsiz = spsiz / 2;    else      spsiz = (spsiz / 4) * 5;    if (spsiz < 20) spsiz = 20;    if (spsiz > spmax) spsiz = spmax;    debug(F101,"rcalcpsiz new spsiz","",spsiz);    numerrs = 0;    return;#endif}/*  R E S E N D  --  Retransmit packet n.  *//*  Returns 0 or positive on success (the number of retries for packet n).  On failure, returns a negative number, and an error message is placed  in recpkt.*/intresend(n) int n; {			/* Send packet n again. */    int j, k;    debug(F101,"resend seq","",n);    k = chkwin(n,winlo,wslots);		/* See if packet in current window */    j = -1;				/* Assume it's lost */    if (k == 0) j = sseqtbl[n];		/* See if we still have a copy of it */    if (k != 0 || j < 0) {		/* If not.... */	if (nakstate && k == 1) {/*  Packet n is in the previous window and we are the file receiver.  We already sent the ACK and deallocated its buffer so we can't just   retransmit the ACK.  Rather than give up, we try some tricks...*/	    if (n == 0 && spackets < 63 && myinit[0]) { /* ACK to Send-Init *//*  If the packet number is 0, and we're at the beginning of a protocol  operation (spackets < 63), then we have to resend the ACK to an I or S  packet, complete with parameters in the data field.  So we take a chance and  send a copy of the parameters in an ACK packet with block check type 1.*/		int bctlsav;		/* Temporary storage */		int bctusav;		bctlsav = bctl;		/* Save current block check length */		bctusav = bctu;		/* and type */		bctu = bctl = 1;	/* Set block check to 1 */		spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);		logpkt('#',n,(CHAR *)"<reconstructed>"); /* Log it */		bctu = bctusav;		/* Restore block check type */		bctl = bctlsav;		/* and length */	    } else {			/* Not the first packet *//*  It's not the first packet of the protocol operation.  It's some other packet  that we have already ACK'd and forgotten about.  So we take a chance and  send an empty ACK using the current block-check type.  Usually this will  work out OK (like when acking Data packets), and no great harm will be done  if it was some other kind of packet (F, etc).  If we are requesting an  interruption of the file transfer, the flags are still set, so we'll catch  up on the next packet.*/		spack('Y',n,0,(CHAR *) "");		logpkt('#',n,(CHAR *)"<faith>"); /* Log it */	    }	    retrans++;	    screen(SCR_PT,'%',(long)pktnum,"(resend)");	    return(0);	} else {/*  Packet number is not in current or previous window.  We seem to hit this  code occasionally at the beginning of a transaction, for apparently no good  reason.  Let's just log it for debugging, send nothing, and try to proceed  with the protocol rather than killing it.*/	    debug(F101,"RESEND PKT NOT IN WINDOW","",n);	    debug(F101,"RESEND k","",k);#ifdef COMMENT	    sprintf((char *)recpkt,		    "   resend error: NIW, n=%d, k=%d.",n,k);	    return(-2);#else	    return(0);#endif /* COMMENT */	}    }/* OK, it's in the window and it's not lost. */    debug(F101,"resend pktinfo index","",k);    if (s_pkt[j].pk_rtr++ > maxtry) {	/* Found it but over retry limit */	strcpy((char *)recpkt,"Too many retries.");	return(-1);    }    debug(F101," retry","",s_pkt[j].pk_rtr); /* OK so far */    dumpsbuf();				/* (debugging) */    if (s_pkt[j].pk_typ == ' ') {	/* Incompletely formed packet */	if (nakstate) {			/* (This shouldn't happen any more) */	    nack(n);	    retrans++;	    screen(SCR_PT,'%',(long)pktnum,"(resend)");	    return(s_pkt[j].pk_rtr);	} else {			/* No packet to resend! */#ifdef COMMENT/*  This happened (once) while sending a file with 2 window slots and typing  X to the sender to cancel the file.  But since we're cancelling anyway,  no need to give a scary message.*/	    sprintf((char *)recpkt,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -