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

📄 ckcfn2.c

📁 C-Kermit源码。是使用串口/Modem和网络通讯的程序
💻 C
📖 第 1 页 / 共 5 页
字号:
nack(n) int n; {    int i, x;    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...  */    x = spack('N',n,0,(CHAR *) "");	/* NAKs never have data. */    return(x);}#ifndef NEWDPL				/* This routine no longer used *//* * (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)			/* Sliding windows */      x = (long) (npad+5+bctr);		/* packet only, don't count ack */    else				/* Stop-n-wait */      x = (long) (npad+5+3+bctr+5+bctr); /* count packet and ack. */    /* 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 */    debug(F101,"rcalcpsiz numerrs","",numerrs);    debug(F101,"rcalcpsiz spsiz","",spsiz);    if (spackets < 3) {	numerrs = 0;	return;    }    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;#endif /* COMMENT */}#endif /* NEWDPL *//*  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, x;#ifdef GFTIMER    CKFLOAT t1 = 0.0, t2 = 0.0;#endif /* GFTIMER */    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 */		x = spack('Y',0,(int)strlen((char *)myinit),(CHAR *)myinit);		if (x < 0) return(x);		logpkt('#',n,(CHAR *)"<reconstructed>",0); /* 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.*/		x = spack('Y',n,0,(CHAR *) "");		if (x < 0) return(x);	    }	    retrans++;	    xxscreen(SCR_PT,'%',(long)pktnum,"Retransmission");	    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);	    return(0);	}    }/* 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 */	xitsta |= what;	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++;	    xxscreen(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,  there's no need to give a scary message.*/	    sprintf((char *)epktmsg,		    "resend logic error: NPS, n=%d, j=%d.",n,j);	    return(-2);#else/* Just ignore it. */	    return(0);#endif /* COMMENT */	}    }#ifdef DEBUG#ifdef GFTIMER    if (deblog) t1 = gftimer();#endif /* GFTIMER */#endif /* DEBUG */    /* Everything ok, send the packet */#ifdef CK_TIMERS    if (timint > 0)      srttbl[n] = gtimer();		/* Update the timer */#endif /* CK_TIMERS */    x = ttol(s_pkt[j].pk_adr,s_pkt[j].pk_len);#ifdef DEBUG#ifdef GFTIMER    if (deblog)  {	t2 = gftimer();	debug(F101,"resend ttol msec","",(long)((t2-t1)*1000.0));    }#endif /* GFTIMER */#endif /* DEBUG */    debug(F101,"resend ttol returns","",x);    retrans++;				/* Count a retransmission */    xxscreen(SCR_PT,'%',(long)pktnum,"(resend)"); /* Tell user about resend */    logpkt('S',n,s_pkt[j].pk_adr, s_pkt[j].pk_len); /* Log the resent packet */    return(s_pkt[j].pk_rtr);		/* Return the number of retries. */}/*  E R R P K T  --  Send an Error Packet  */interrpkt(reason) CHAR *reason; {		/* ...containing the reason given */    extern int rtimo, state, justone;    int x, y;    czseen = 1;				/* Also cancels batch */    state = 0;				/* Reset protocol state */    debug(F110,"errpkt",reason,0);    tlog(F110,"Protocol Error:",(char *)reason,0L);    xxscreen(SCR_EM,0,0L,reason);    encstr(reason);    x = spack('E',pktnum,size,data);    ckstrncpy((char *)epktmsg,(char *)reason,PKTMSGLEN);    y = quiet; quiet = 1; epktsent = 1;	/* Close files silently. */    clsif(); clsof(discard);    quiet = y;/*  I just sent an E-packet.  I'm in local mode, I was receiving a file,  I'm not a server, and sliding windows are in use.  Therefore, there are  likely to be a bunch of packets already "in the pipe" on their way to me  by the time the remote sender gets the E-packet.  So the next time I  CONNECT or try to start another protocol operation, I am likely to become  terribly confused by torrents of incoming material.  To prevent this,  the following code soaks up packets from the connection until there is an  error or timeout, without wasting too much time waiting.  Exactly the same problem occurs when I am in remote mode or if I am  in server mode with the justone flag set.  In remote mode not only  does the packet data potentially get echo'd back to the sender which  is confusing to the user in CONNECT mode, but it also may result in the  host performing bizarre actions such as suspending the process if ^Z is  unprefixed, etc.  Furthermore, thousands of packets bytes in the data stream prevent the  client from being able to process Telnet Kermit Option negotiations  properly.*/#ifdef STREAMING    /* Because streaming sets the timeout to 0... */    if (streaming) {	timint = rcvtimo = rtimo;	streaming = 0;    }#endif /* STREAMING */    if (what == W_RECV &&        (!server || server && justone) &&        (wslots > 1 || streaming)) {#ifdef GFTIMER	CKFLOAT oldsec, sec = (CKFLOAT) 0.0;#else	int oldsec, sec = 0;#endif /* GFTIMER */	debug(F101,"errpkt draining","",wslots);	xxscreen(SCR_ST,ST_MSG,0l,"Draining incoming packets, wait...");	while (x > -1) {		/* Don't bother if no connection */	    oldsec = sec;#ifdef GFTIMER	    sec = gftimer();	    if (oldsec != (CKFLOAT) 0.0)	      timint = rcvtimo = (int) (sec - oldsec + 0.5);#else	    sec = gtimer();	    if (oldsec != 0)	      timint = rcvtimo = sec - oldsec + 1;#endif /* GFTIMER */	    if (timint < 1)	      timint = rcvtimo = 1;	    msleep(50);			/* Allow a bit of slop */	    x = rpack();		/* Read a packet */	    if (x == 'T' || x == 'z')	/* Timed out means we're done */	      break;	    xxscreen(SCR_PT,x,rsn,"");	/* Let user know */	}	xxscreen(SCR_ST,ST_MSG,0l,"Drain complete.");    }    if (what < W_CONNECT)      xitsta |= what;			/* Remember what failed. */    success = 0;    return(y);}/* scmd()  --  Send a packet of the given type */int#ifdef CK_ANSICscmd(char t, CHAR *dat)#elsescmd(t,dat) char t; CHAR *dat;#endif /* CK_ANSIC *//* scmd */ {    int x;    extern char * srimsg;    debug(F000,"scmd",dat,t);    if (encstr(dat) < 0) {		/* Encode the command string */	srimsg = "String too long";	return(-1);    }    x = spack(t,pktnum,size,data);    debug(F101,"scmd spack","",x);    return(x);}/* Compose and Send GET packet */struct opktparm {			/* O-Packet item list */    CHAR * opktitem;    struct opktparm * opktnext;};struct opktparm * opkthead = NULL;	/* Linked list of O-packet fields */int opktcnt = 0;			/* O-Packet counter */char * srimsg = NULL;			/* GET-Packet error message *//* S O P K T  --  Send O-Packet *//*  Sends one O-Packet each time called, using first-fit method of filling  the packet from linked list of parameters pointed to by opkthead.  To be called repeatedly until list is empty or there is an error.  Returns:   -1 on failure.    0 on success and no more fields left to send.    1 on success but with more fields left to be sent.*/intsopkt() {    int n = 0;				/* Field number in this packet */    int rc = 0;				/* Return code */    int len = 0;			/* Data field length */    char c = NUL;    struct opktparm * o = NULL;    struct opktparm * t = NULL;    struct opktparm * prev = NULL;    CHAR * dsave = data;    int x, ssave = spsiz;    srimsg = NULL;			/* Error message */    o = opkthead;			/* Point to head of list */    if (!o) {				/* Oops, no list... */	srimsg = "GET Packet Internal Error 1";	debug(F100,"sopkt NULL list","",0);	return(-1);    }    while (o) {				/* Go thru linked list... */	c = *(o->opktitem);		/* Parameter code */	debug(F000,"sopkt",o->opktitem,c);	x = encstr((CHAR *)o->opktitem);	debug(F111,"sopkt encstr",dsave,x);	if (x < 0) {			/* Encode this item */	    if (n == 0) {		/* Failure, first field in packet */		debug(F100,"sopkt overflow","",0);		spsiz = ssave;		/* Restore these */		data = dsave;		o = opkthead;		/* Free linked list */		while (o) {		    if (o->opktitem) free(o->opktitem);		    t = o->opktnext;		    free(o);		    o = t;		}		opkthead = NULL;		srimsg = "GET Packet Too Long for Server";		return(-1);		/* Fail */	    } else {			/* Not first field in packet */		debug(F110,"sopkt leftover",o->opktitem,0);		prev = o;		/* Make this one the new previous */		o = o->opktnext;	/* Get next */		c = NUL;		/* So we know we're not done */		*data = NUL;		/* Erase any partial encoding */		continue;	

⌨️ 快捷键说明

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