📄 ckcfn2.c
字号:
/* Now fill the packet */ mydata[i++] = mystch; /* MARK */ lp = i++; /* Position of LEN, fill in later */ mydata[i++] = tochar(n); /* SEQ field */ mydata[i++] = pkttyp; /* TYPE field */ j = len + bctl; /* Length of data + block check */ if (longpkt) { /* Long packet? */ int x; /* Yes, work around SCO Xenix/286 */#ifdef CKTUNING unsigned int chk;#endif /* CKTUNING */ x = j / 95; /* compiler bug... */ mydata[lp] = tochar(0); /* Set LEN to zero */ mydata[i++] = tochar(x); /* Extended length, high byte */ mydata[i++] = tochar(j % 95); /* Extended length, low byte */#ifdef CKTUNING /* Header checksum - skip the function calls and loops */ chk = (unsigned) mydata[lp] + (unsigned) mydata[lp+1] + (unsigned) mydata[lp+2] + (unsigned) mydata[lp+3] + (unsigned) mydata[lp+4] ; mydata[i++] = tochar((CHAR) ((((chk & 0300) >> 6) + chk) & 077));#else mydata[i] = '\0'; /* Terminate for header checksum */ mydata[i++] = tochar(chk1(mydata+lp,5));#endif /* CKTUNING */ } else mydata[lp] = tochar(j+2); /* Normal LEN *//* When sending a file, the data is already in the right place. If it weren't, it might make sense to optimize this section by using memcpy or bcopy (neither of which are portable), but only if our packets were rather long. When receiving, we're only sending ACKs so it doesn't matter. So count the following loop as a sleeping dog.*/ if (copy) /* Data field built in place? */ for ( ; len--; i++) mydata[i] = *d++; /* No, must copy. */ else /* Otherwise, */ i += len; /* Just skip past data field. */ mydata[i] = '\0'; /* Null-terminate for checksum calc. */ switch (bctu) { /* Block check */ case 1: /* 1 = 6-bit chksum */ mydata[i++] = tochar(chk1(mydata+lp,i-lp)); break; case 2: /* 2 = 12-bit chksum */ j = chk2(mydata+lp,i-lp); mydata[i++] = (unsigned)tochar((j >> 6) & 077); mydata[i++] = (unsigned)tochar(j & 077); break; case 3: /* 3 = 16-bit CRC */ crc = chk3(mydata+lp,i-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,i-lp); mydata[i++] = (unsigned)(tochar((unsigned)(((j >> 6) & 077) + 1))); mydata[i++] = (unsigned)(tochar((unsigned)((j & 077) + 1))); break; } loglen = i; 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 NVT specification, unless user said RAW. If NEWLINE-MODE is set to LF instead of CR, we still send CR-NUL on a NVT connection and CR on a binary connection.*/ if (#ifdef STREAMING !dontsend &&#endif /* STREAMING */ ((network && ttnproto == NP_TELNET) || (!local && sstelnet)) && seol == CR) { switch (TELOPT_ME(TELOPT_BINARY) ? tn_b_nlm : tn_nlm) { case TNL_CR: /* NVT or BINARY */ break; case TNL_CRNUL: mydata[i++] = NUL; break; case TNL_CRLF: mydata[i++] = LF; break; } }#endif /* TCPSOCKET */ mydata[i] = '\0'; /* Terminate string */ if (#ifdef STREAMING !dontsend &&#endif /* STREAMING */ pktlog ) /* Save a function call! */ logpkt('s',n,mydata,loglen); /* Log the packet */ /* (PWP) add the parity quickly at the end */ if (parity) { switch (parity) { case 'e': /* Even */ for (cp = &mydata[i-1]; cp >= mydata; cp--) *cp = p_tbl[*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 = p_tbl[*cp] ^ 128; break; case 's': /* Space */ for (cp = &mydata[i-1]; cp >= mydata; cp--) *cp &= 127; break; } } if (pktpaus) msleep(pktpaus); /* Pause if requested */ x = 0; if (npad) {#ifdef STREAMING if (dontsend) x = 0; else#endif /* STREAMING */ x = ttol(padbuf,npad); /* Send any padding */ } if (x > -1) {#ifdef CK_TIMERS if (timint > 0) { if (pkttyp == 'N') srttbl[n > 0 ? n-1 : 63] = gtimer(); else srttbl[n] = gtimer(); }#endif /* CK_TIMERS */ spktl = i; /* Remember packet length */ if (k > -1) s_pkt[k].pk_len = spktl; /* also in packet info structure */#ifdef DEBUG#ifdef GFTIMER/* This code shows (in the debug log) how long it takes write() to execute. Sometimes on a congested TCP connection, it can surprise you -- 90 seconds or more...*/ if (#ifdef STREAMING !dontsend &&#endif /* STREAMING */ deblog ) t1 = gftimer();#endif /* GFTIMER */#endif /* DEBUG */#ifdef STREAMING if (dontsend) { debug(F000,"STREAMING spack skipping","",pkttyp); x = 0; } else#endif /* STREAMING */ x = ttol(mydata,spktl); /* Send the packet */ }#ifdef STREAMING if (!dontsend) {#endif /* STREAMING */ debug(F101,"spack spktl","",spktl); debug(F101,"spack ttol returns","",x); if (x < 0) { /* Failed. */ if (local && x < -1) { xxscreen(SCR_ST,ST_ERR,0L,"FAILED: Connection lost"); /* We can't send an E packet because the connection is lost. */ epktsent = 1; /* So pretend we sent one. */ fatalio = 1; /* Remember we got a fatal i/o error */#ifdef CKLOGDIAL dologend();#endif /* CKLOGDIAL */ ckstrncpy((char *)epktmsg,"Connection lost",PKTMSGLEN); } return(x); } if (spktl > maxsend) /* Keep track of longest packet sent */ maxsend = spktl;#ifdef DEBUG#ifdef GFTIMER if (deblog) { /* Log elapsed time for write() */ t2 = gftimer(); debug(F101,"spack ttol msec","",(long)((t2-t1)*1000.0)); }#endif /* GFTIMER */#endif /* DEBUG */#ifdef STREAMING }#endif /* STREAMING */ sndtyp = pkttyp; /* Remember packet type for echos */ if (!dontsend) { /* If really sent, */ spackets++; /* count it. */ flco += spktl; /* Count the characters */ tlco += spktl; /* for statistics... */#ifdef DEBUG if (deblog) { /* Save two function calls! */ dumpsbuf(); /* Dump send buffers to debug log */ debug(F111,"spack calling screen, mydata=",mydata,n); }#endif /* DEBUG */ } if (local) { int x = 0; if (fdispla != XYFD_N) x = 1; if ((fdispla == XYFD_B) && (pkttyp == 'D' || pkttyp == 'Y')) x = 0; if (x) xxscreen(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,len) register CHAR *pkt; register int len; { register unsigned int chk;#ifdef CKTUNING#ifdef COMMENT register unsigned int m; /* Avoid function call */ m = (parity) ? 0177 : 0377; for (chk = 0; len-- > 0; pkt++) chk += *pkt & m;#else chk = 0; while (len-- > 0) chk += (unsigned) *pkt++;#endif /* COMMENT */#else chk = chk2(pkt,len);#endif /* CKTUNING */ chk = (((chk & 0300) >> 6) + chk) & 077; debug(F101,"chk1","",chk); return((int) chk);}/* C H K 2 -- Compute the numeric sum of all the bytes in the packet. */unsigned intchk2(pkt,len) register CHAR *pkt; register int len; { register long chk;#ifdef COMMENT register unsigned int m; m = (parity) ? 0177 : 0377; for (chk = 0; len-- > 0; pkt++) chk += *pkt & m;#else /* Parity has already been stripped */ chk = 0L; while (len-- > 0) chk += (unsigned) *pkt++;#endif /* COMMENT */ debug(F101,"chk2","",(unsigned int) (chk & 07777)); 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.*/#ifdef COMMENTunsigned intchk3(pkt,parity,len) register CHAR *pkt; int parity; register int len; { register long c, crc; register unsigned int m; m = (parity) ? 0177 : 0377; for (crc = 0; len-- > 0; pkt++) { c = crc ^ (long)(*pkt & m); crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]); } return((unsigned int) (crc & 0xFFFF));}#elseunsigned intchk3(pkt,len) register CHAR *pkt; register int len; { register long c, crc; for (crc = 0; len-- > 0; pkt++) { c = crc ^ (long)(*pkt); crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]); } debug(F101,"chk3","",(unsigned int) (crc & 0xFFFF)); return((unsigned int) (crc & 0xFFFF));}#endif /* COMMENT *//* N X T P K T -- Next Packet *//* Get packet number of next packet to send and allocate a buffer for it. Returns: 0 on success, with global pktnum set to the packet number; -1 on failure to allocate buffer (fatal); -2 if resulting packet number is outside the current window.*/intnxtpkt() { /* Called by file sender */ int j, n, x; debug(F101,"nxtpkt pktnum","",pktnum); debug(F101,"nxtpkt winlo ","",winlo); n = (pktnum + 1) % 64; /* Increment packet number mod 64 */ debug(F101,"nxtpkt n","",n);#ifdef STREAMING if (!streaming) { x = chkwin(n,winlo,wslots); /* Don't exceed window boundary */ debug(F101,"nxtpkt chkwin","",x); if (x) return(-2); j = getsbuf(n); /* Get a buffer for packet n */ if (j < 0) { debug(F101,"nxtpkt getsbuf failure","",j); return(-1); } }#endif /* STREAMING */ pktnum = n; 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 *)""));}#ifdef STREAMINGintfastack() { /* Acknowledge packet n */ int j, k, n, x; n = winlo; k = rseqtbl[n]; /* First find received packet n. */ debug(F101,"STREAMING fastack k","",k); 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,"STREAMING fastack can't getsbuf","",n); } dontsend = 1; x = spack('Y',n,0,(CHAR *)""); /* Now send it (but not really) */ dontsend = 0; if (x < 0) return(x); debug(F101,"STREAMING fastack x","",x); 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);}#endif /* STREAMING */intackns(n,s) int n; CHAR *s; { /* Acknowledge packet n */ int j, k, x; debug(F111,"ackns",s,n); k = rseqtbl[n]; /* First find received packet n. */ debug(F101,"ackns k","",k); 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); } x = spack('Y',n,(int)strlen((char *)s),s); /* Now send it. */ if (x < 0) return(x); 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. */ if (!s) s = (CHAR *)""; 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.*/int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -