📄 ckcfn2.c
字号:
spack((char)'H',pktnum,size,data); /* Send the packet. */ else spack((char)(reget ? 'J' : 'R'),pktnum,size,data); /* Send the packet. */ return(0);}/* K S T A R T -- Checks for a Kermit packet while in terminal mode. */#ifdef CK_APCint #ifdef CK_ANSICkstart(CHAR ch)#elsekstart(ch) CHAR ch;#endif /* CK_ANSIC *//* kstart */ { static int buflen = 94; static CHAR buf[95]; static CHAR * p = NULL; extern CHAR stchr, eol; if (ch == stchr) { /* Start of packet */ p = buf; *p = ch; debug(F101,"kstart SOP","",ch); } else if (ch == eol) { /* End of packet */ if (p) { p++; if (p - buf < 94 ) { int rc = 0; *p = ch; p++; *p = NUL; if (rc = chkspkt((char *)buf)) debug(F111,"kstart EOP", buf, ch); p = NULL; if (!rc) return(0); return(rc == 1 ? PROTO_K + 1 : 0 - (PROTO_K + 1)); } else { p = NULL; } } } else if (p) { p++; if (p - buf < 94) *p = ch; else p = NULL; } return(0);}#ifdef CK_XYZ/* Z S T A R T -- Checks for a ZMODEM packet while in terminal mode. */int #ifdef CK_ANSICzstart(CHAR ch)#elsezstart(ch) CHAR ch;#endif /* CK_ANSIC *//* zstart */ { static CHAR * matchstr = (CHAR *) "\030B00"; /* "rz\r**\030B00000000000000\r\033J\021"; */ static CHAR * p = NULL; if (!ch) return(0); if (!p) p = matchstr; if (ch == *p) { p++; if (*p == '\0') { p = matchstr; debug(F100, "zstart Zmodem SOP","",0); return(PROTO_Z + 1); } } else p = matchstr; return(0);}#endif /* CK_XYZ *//* C H K S P K T -- Check if buf contains a valid S or I packet */intchkspkt(buf) char *buf; { int buflen; int len = -1; CHAR chk; char type = 0; char *s = buf; if (!buf) return(0); buflen = strlen(buf); if (buflen < 5) return(0); /* Too short */ if (*s++ != stchr) return(0); /* SOH */ len = xunchar(*s++); /* Length */ if (len < 0) return(0); if (*s++ != SP) return(0); /* Sequence number */ type = *s++; /* Type */ if (type != 'S' && type != 'I') return(0); if (buflen < len + 2) return(0); s += (len - 3); /* Position of checksum */ chk = (CHAR) (*s); /* Checksum */ *s = NUL; if (xunchar(chk) != chk1((CHAR *) (buf+1))) return(0); /* Check it */ *s = chk; return(type == 'S' ? 1 : 2);}#endif /* CK_APC *//* R P A C K -- Read a Packet *//* rpack reads a packet and returns the packet type, or else Q if the packet was invalid, or T if a timeout occurred. Upon successful return, sets the values of global rsn (received sequence number), rln (received data length), and rdatap (pointer to null-terminated data field), and returns the packet type.*/intrpack() { register int i, j, x, lp; /* Local variables */ int k, type, chklen; unsigned crc; CHAR pbc[4]; /* Packet block check */ CHAR *sohp; /* Pointer to SOH */ CHAR e; /* Packet end character */#ifdef GETMSEC long t1, t2;#endif /* GETMSEC */ debug(F101,"entering rpack, pktnum","",pktnum);#ifndef OLDCHKINT if (chkint() < 0) /* Check for console interrupts. */ return('z');#endif /* OLDCHKINT */ k = getrbuf(); /* Get a new packet input buffer. */ debug(F101,"rpack getrbuf","",k); if (k < 0) return(-1); /* Return like this if none free. */ if (pktmsg) *pktmsg = NUL; recpkt = r_pkt[k].bf_adr; *recpkt = '\0'; /* Clear receive buffer. */ sohp = recpkt; /* Initialize pointers to it. */ rdatap = recpkt; rsn = rln = -1; /* In case of failure. */ e = (turn) ? turnch : eol; /* Use any handshake char for eol *//* Try to get a "line". */#ifdef GETMSEC if (deblog) t1 = getmsec();#endif /* GETMSEC */#ifdef PARSENSE#ifdef UNIX/* So far the final turn argument is only for ck[uvdl]tio.c. Should be added to the others too. (turn == handshake character.)*/ j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);#else#ifdef VMS j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);#else#ifdef datageneral j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);#else#ifdef STRATUS j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);#else#ifdef OS2 j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);#else#ifdef OSK j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr,turn);#else j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e,stchr);#endif /* OSK */#endif /* OS2 */#endif /* STRATUS */#endif /* datageneral */#endif /* VMS */#endif /* UNIX */ if (parity != ttprty) autopar = 1; parity = ttprty; #else /* !PARSENSE */ j = ttinl(recpkt,r_pkt[k].bf_len - 1,rcvtimo,e);#endif /* PARSENSE */#ifdef GETMSEC if (deblog) { t2 = getmsec(); if (t2 > -1L && t1 > -1L) debug(F101,"rpack ttinl time","",t2-t1); else debug(F100,"rpack ttinl time error","",0); }#endif /* GETMSEC */ if (j < 0) { debug(F101,"rpack: ttinl fails","",j); /* Otherwise, */ freerbuf(k); /* Free this buffer */ if (j < -1) { /* Bail out if ^C^C typed. */ debug(F101,"rpack ^C server","",server); debug(F101,"rpack ^C en_fin","",en_fin); if (server == 0) return(j); /* But not if in server mode */ else if (en_fin) return(j); /* with DISABLE FINISH */ else return(-2); } if (nakstate) /* Call it a timeout. */ screen(SCR_PT,'T',(long)winlo,""); else screen(SCR_PT,'T',(long)pktnum,""); logpkt('r',-1,(CHAR *)"<timeout>"); if (flow == 1) ttoc(XON); /* In case of Xoff blockage. */ return('T'); } rpktl = j; tlci += j; /* All OK, Count the characters. */ flci += j;#ifndef PARSENSE/* THEN eliminate this loop... */ for (i = 0; (recpkt[i] != stchr) && (i < j); i++) sohp++; /* Find mark */ if (i++ >= j) { /* Didn't find it. */ logpkt('r',-1,"<timeout>"); freerbuf(k); return('T'); } #else i = 1;#endif /* PARSENSE */ rpackets++; lp = i; /* Remember LEN position. */ if ((j = xunchar(recpkt[i++])) == 0) { if ((j = lp+5) > MAXRP) return('Q'); /* Long packet */ x = recpkt[j]; /* Header checksum. */ recpkt[j] = '\0'; /* Calculate & compare. */ if (xunchar(x) != chk1(recpkt+lp)) { freerbuf(k); logpkt('r',-1,(CHAR *)"<crunched:hdr>"); screen(SCR_PT,'%',(long)pktnum,"Bad packet header"); return('Q'); } recpkt[j] = x; /* Checksum ok, put it back. */ rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctl; j = 3; /* Data offset. */ } else if (j < 3) { debug(F101,"rpack packet length less than 3","",j); freerbuf(k); logpkt('r',-1,(CHAR *)"<crunched:len>"); screen(SCR_PT,'%',(long)pktnum,"Bad packet length"); return('Q'); } else { rln = j - bctl - 2; /* Regular packet */ j = 0; /* No extended header */ } rsn = xunchar(recpkt[i++]); /* Sequence number */ logpkt('r',rsn,sohp); if (rsn < 0 || rsn > 63) { debug(F101,"rpack bad sequence number","",rsn); freerbuf(k); logpkt('r',rsn,(CHAR *)"<crunched:seq>"); screen(SCR_PT,'%',(long)pktnum,"Bad sequence number"); return('Q'); }/* If this packet has the same type as the packet just sent, assume it is an echo and ignore it. Don't even bother with the block check calculation: even if the packet is corrupted, we don't want to NAK an echoed packet. (And we certainly don't want to NAK an ACK or NAK!)*/ type = recpkt[i++]; /* Get packet's TYPE field */ if (type == sndtyp || (nakstate && (type == 'N' /* || type == 'Y' */ ))) { debug(F000,"rpack echo","",type); /* If it's an echo */ freerbuf(k); /* Free this buffer */ logpkt('#',rsn,(CHAR *)"<echo:ignored>"); return('e'); /* return special (lowercase) code */ }/* Separate the data from the block check, accounting for the case where a packet was retransmitted after the block check switched.*/ if (type == 'I' || type == 'S') { /* I & S packets always have type 1 */ chklen = 1; rln = rln + bctl - 1; } else if (type == 'N') { /* A NAK packet never has data */ chklen = xunchar(recpkt[lp]) - 2; rln = rln + bctl - chklen; } else chklen = bctl; debug(F101,"rpack bctl","",bctl); debug(F101,"rpack chklen","",chklen); i += j; /* Buffer index of DATA field */ rdatap = recpkt+i; /* Pointer to DATA field */ if ((j = rln + i) > r_pkt[k].bf_len ) { /* Make sure it fits */ debug(F101,"packet sticks out too far","",j); freerbuf(k); logpkt('r',rsn,(CHAR *)"<overflow>"); return('Q'); } for (x = 0; x < chklen; x++) /* Copy the block check */ pbc[x] = recpkt[j+x]; pbc[x] = '\0'; /* Null-terminate block check string */ recpkt[j] = '\0'; /* and the packet DATA field. */ if (chklen == 2 && bctu == 4) { /* Adjust for Blank-Free-2 */ chklen = 4; /* (chklen is now a misnomer...) */ debug(F100,"rpack block check B","",0); } switch (chklen) { /* Check the block check */ case 1: /* Type 1, 6-bit checksum */ if (xunchar(*pbc) != chk1(recpkt+lp)) { debug(F110,"checked chars",recpkt+lp,0); debug(F101,"block check","",(int) xunchar(*pbc)); debug(F101,"should be","",chk1(recpkt+lp)); freerbuf(k); logpkt('r',-1,(CHAR *)"<crunched:chk1>"); screen(SCR_PT,'%',(long)pktnum,"Checksum error"); return('Q'); } break; case 2: /* Type 2, 12-bit checksum */ x = xunchar(*pbc) << 6 | xunchar(pbc[1]); if (x != chk2(recpkt+lp)) { /* No match */ if (type == 'E') { /* Allow E packets to have type 1 */ recpkt[j++] = pbc[0]; recpkt[j] = '\0'; if (xunchar(pbc[1]) == chk1(recpkt+lp)) break; else recpkt[--j] = '\0'; } debug(F110,"checked chars",recpkt+lp,0); debug(F101,"block check","", x); debug(F101,"should be","", (int) chk2(recpkt+lp)); freerbuf(k); logpkt('r',-1,(CHAR *)"<crunched:chk2>"); screen(SCR_PT,'%',(long)pktnum,"Checksum error"); return('Q'); } break; case 3: /* Type 3, 16-bit CRC */ crc = (xunchar(pbc[0]) << 12) | (xunchar(pbc[1]) << 6) | (xunchar(pbc[2])); if (crc != chk3(recpkt+lp,parity)) { if (type == 'E') { /* Allow E packets to have type 1 */ recpkt[j++] = pbc[0]; recpkt[j++] = pbc[1]; recpkt[j] = '\0'; if (xunchar(pbc[2]) == chk1(recpkt+lp)) break; else { j -=2; recpkt[j] = '\0'; } } debug(F110,"checked chars",recpkt+lp,0); debug(F101,"block check","",xunchar(*pbc)); debug(F101,"should be","",(int) chk3(recpkt+lp,parity)); freerbuf(k); logpkt('r',-1,(CHAR *)"<crunched:chk3>"); screen(SCR_PT,'%',(long)pktnum,"CRC error"); return('Q'); } break; case 4: /* Type 4 = Type 2, no blanks. */ x = (unsigned)((xunchar(*pbc) - 1) << 6) | (unsigned)(xunchar(pbc[1]) - 1); if (x != chk2(recpkt+lp)) { if (type == 'E') { /* Allow E packets to have type 1 */ recpkt[j++] = pbc[0]; recpkt[j] = '\0'; if (xunchar(pbc[1]) == chk1(recpkt+lp)) break; else recpkt[--j] = '\0'; } debug(F101,"bad type B block check","",x); freerbuf(k); logpkt('r',-1,(CHAR *)"<crunched:chkb>"); screen(SCR_PT,'%',(long)pktnum,"Checksum error"); return('Q'); } break; default: /* Shouldn't happen... */ freerbuf(k); logpkt('r',-1,(CHAR *)"<crunched:chkx>"); screen(SCR_PT,'%',(long)pktnum,"(crunched)"); return('Q'); } debug(F101,"rpack block check OK","",rsn);/* Now we can believe the sequence number, and other fields. *//* Here we violate strict principles of layering, etc, and look at the *//* packet sequence number. If there's already a packet with the same *//* number in the window, we remove this one so that the window will not *//* fill up. */ if ((x = rseqtbl[rsn]) != -1) { /* Already a packet with this number */ retrans++; /* Count it for statistics */ debug(F101,"rpack got dup","",rsn); logpkt('r',rsn,(CHAR *)"<duplicate>"); freerbuf(x); /* Free old buffer, keep new packet. */ r_pkt[k].pk_rtr++; /* Count this as a retransmission
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -