📄 zmodemt.c
字号:
{ZFERR,ZmGotAbort,1,1,TFinish}, {ZCOMMAND,ZmGotCommand,0,0,CommandData}, {ZSTDERR,ZmGotStderr,0,0,StderrData}, {99,ZmZPF,0,0,TInit}, } ; /* sent ZFILE, waiting for response */ StateTable FileWaitOps[] = { {ZRPOS,ZmSendFileData,1,0,Sending}, {ZSKIP,ZmSkipFile,1,0,FileWait}, {ZCRC,ZmSendFileCrc,1,0,FileWait}, {ZNAK,ZmSendFilename,1,0,FileWait}, {ZRINIT,ZmSendFilename,1,1,FileWait}, /* rcvr confused, retry file */ {ZABORT,ZmGotAbort,1,1,TFinish}, {ZFERR,ZmGotAbort,1,1,TFinish}, {ZCHALLENGE,ZmAnswerChallenge,1,0,FileWait}, {ZCOMMAND,ZmGotCommand,0,0,CommandData}, {ZSTDERR,ZmGotStderr,0,0,StderrData}, {99,ZmZPF,0,0,FileWait}, } ; /* sent file CRC, waiting for response */ StateTable CrcWaitOps[] = { {ZRPOS,ZmSendFileData,1,0,Sending}, {ZSKIP,ZmSkipFile,1,0,FileWait}, {ZNAK,ZmSendFileCrc,1,0,CrcWait}, {ZRINIT,ZmSendFilename,1,1,FileWait}, /* rcvr confused, retry file */ {ZABORT,ZmGotAbort,1,1,TFinish}, {ZFERR,ZmGotAbort,1,1,TFinish}, {ZCRC,ZmSendFileCrc,0,0,CrcWait}, {ZCHALLENGE,ZmAnswerChallenge,0,0,CrcWait}, {ZCOMMAND,ZmGotCommand,0,0,CommandData}, {ZSTDERR,ZmGotStderr,0,0,StderrData}, {99,ZmZPF,0,0,CrcWait}, } ; /* sending data, interruptable */ StateTable SendingOps[] = { {ZACK,ZmGotSendAck,0,0,Sending}, {ZRPOS,ZmGotSendPos,1,1,Sending}, {ZSKIP,ZmSkipFile,1,1,FileWait}, {ZNAK,ZmGotSendNak,1,1,Sending}, {ZRINIT,ZmSendFilename,1,1,FileWait}, /* rcvr confused, retry file */ {ZABORT,ZmGotAbort,1,1,TFinish}, {ZFERR,ZmGotAbort,1,1,TFinish}, {99,ZmZPF,0,0,SendWait}, } ; /* sent data, need to send EOF */ StateTable SendDoneOps[] = { {ZACK,ZmGotSendDoneAck,0,0,SendWait}, {ZRPOS,ZmGotSendPos,1,1,Sending}, {ZSKIP,ZmSkipFile,1,1,FileWait}, {ZNAK,ZmGotSendNak,1,1,Sending}, {ZRINIT,ZmSendFilename,1,1,FileWait}, /* rcvr confused, retry file */ {ZABORT,ZmGotAbort,1,1,TFinish}, {ZFERR,ZmGotAbort,1,1,TFinish}, {99,ZmZPF,0,0,SendWait}, } ; /* sending data, waiting for ACK */ StateTable SendWaitOps[] = { {ZACK,ZmGotSendWaitAck,0,0,Sending}, {ZRPOS,ZmGotSendPos,0,0,SendWait}, {ZSKIP,ZmSkipFile,1,1,FileWait}, {ZNAK,ZmGotSendNak,0,0,Sending}, {ZRINIT,ZmSendFilename,1,1,FileWait}, /* rcvr confused, retry file */ {ZABORT,ZmGotAbort,1,1,TFinish}, {ZFERR,ZmGotAbort,1,1,TFinish}, {99,ZmZPF,0,0,SendWait}, } ; /* sent ZEOF, waiting for new RINIT */ StateTable SendEofOps[] = { {ZRINIT,ZmSkipFile,1,0,TStart}, /* successful completion */ {ZACK,ZmIgnore,0,0,SendEof}, /* probably ACK from last packet */ {ZRPOS,ZmGotSendPos,1,1,SendWait}, {ZSKIP,ZmSkipFile,1,1,TStart}, {ZNAK,ZmResendEof,1,0,SendEof}, {ZRINIT,ZmSendFilename,1,1,FileWait}, /* rcvr confused, retry file */ {ZABORT,ZmGotAbort,1,1,TFinish}, {ZFERR,ZmGotAbort,1,1,TFinish}, {99,ZmZPF,0,0,SendEof}, } ; StateTable TFinishOps[] = { {ZFIN,ZmOverAndOut,1,1,Done}, {ZNAK,ZmTFinish,1,1,TFinish}, {ZRINIT,ZmTFinish,1,1,TFinish}, {ZABORT,ZmGotAbort,1,1,TFinish}, {ZFERR,ZmGotAbort,1,1,TFinish}, {99,ZmZPF,0,0,TFinish}, } ;extern char *hdrnames[] ; /* Received Rinit. Usually received while in start state, * this can also be an attempt to resync after a protocol * failure */static int ZmGotRinit( ZModem *info ){ info->bufsize = info->hdrData[1] + info->hdrData[2]*256 ; info->zrinitflags = info->hdrData[4] + info->hdrData[3]*256 ; info->crc32 = info->zrinitflags & CANFC32 ; info->escCtrl = info->zrinitflags & ESCCTL ; info->escHibit = info->zrinitflags & ESC8 ; /* Full streaming: If receiver can overlap I/O, and if * the sender can sample the reverse channel without hanging, * and the receiver has not specified a buffer size, then we * can simply blast away with ZCRCG packets. If the receiver * detects an error, it sends an attn sequence and a new ZRPOS * header to restart the file where the error occurred. * * [note that zmodem8.doc does not define how much noise is * required to trigger a ZCRCW packet. We arbitrarily choose * 64 bytes] * * If 'windowsize' is nonzero, and the receiver can do full * duplex, ZCRCQ packets are sent instead of ZCRCG, to keep track * of the number of characters in the queue. If the queue fills * up, we pause and wait for a ZACK. * * * Full Streaming with Reverse Interrupt: If sender cannot * sample the input stream, then we define an Attn sequence * that will be used to interrupt transmission. * * * Full Streaming with Sliding Window: If sender cannot * sample input stream or respond to Attn signal, we send * several ZCRCQ packets until we're sure the receiver must * have sent back at least one ZACK. Then we stop sending and * read that ZACK. Then we send one more packet and so on. * * * Segmented Streaming: If receiver cannot overlap I/O or can't do * full duplex and has specified a maximum receive buffer size, * whenever the buffer size is reached, we send a ZCRCW packet. * * TODO: what if receiver can't overlap, but hasn't set a buffer * size? * * ZCRCE: CRC next, frame ends, header follows * ZCRCG: CRC next, frame continues nonstop * ZCRCQ: CRC next, send ZACK, frame continues nonstop * ZCRCW: CRC next, send ZACK, frame ends, header follows */ ZFlowControl(1,info) ; if( (info->zrinitflags & (CANFDX|CANOVIO)) == (CANFDX|CANOVIO) && (SendSample||SendAttn) && info->bufsize == 0 ) { if( info->windowsize == 0 ) { info->Streaming = Full; } else { info->Streaming = StrWindow; } } else if( (info->zrinitflags & (CANFDX|CANOVIO)) == (CANFDX|CANOVIO) && info->bufsize == 0 ) { info->Streaming = SlidingWindow; } else info->Streaming = Segmented;#ifdef ZMODEMLOG zmodemlog("GotRinit[%s]\n", ZmSname(info)) ;#endif // ZMODEMLOG if( AlwaysSinit || info->zsinitflags != 0 || info->attn != NULL ) return(ZmSendZSInit(info)); else return ZmDone ; /* caller now calls ZmTFile() */}static int ZmSendZSInit( ZModem *info ){ int err ; const char *at = (info->attn != NULL) ? info->attn : "" ; u_char fbuf[4] ; int pos; pos = 0; while( *(at + pos) != '\0' ) { pos += 1; } /* TODO: zmodem8.doc states: "If the ZSINIT header specifies * ESCCTL or ESC8, a HEX header is used, and the receiver * activates the specified ESC modes before reading the following * data subpacket." What does that mean? */#ifdef ZMODEMLOG zmodemlog("SendZSInit[%s]\n", ZmSname(info)) ;#endif // ZMODEMLOG info->state = TInit ; fbuf[0] = fbuf[1] = fbuf[2] = 0 ; fbuf[3] = info->zsinitflags ; err = ZXmitHdr(ZSINIT, ZBIN, fbuf, info); if(err) { return(err); } err = ZXmitData(ZBIN, pos+1, ZCRCW, (u_char *)at, info); if(err) { return(err); } return(0);}static int ZmSendFileCrc( ZModem *info ){ u_long crc ; crc = FileCrc(info->filename) ;#ifdef ZMODEMLOG zmodemlog("SendFileCrc[%s]: %lx\n", ZmSname(info), crc) ;#endif //ZMODEMLOG return ZXmitHdrHex(ZCRC, ZEnc4(crc), info) ;}/* Utility: start sending data. */static int ZmStartFileData( ZModem *info ){ int err ; info->offset = info->lastOffset = info->zrposOffset = ZDec4(info->hdrData+1) ; ZFileSeek(info->file, info->offset, info); /* TODO: what if fseek fails? Send EOF? */#ifdef ZMODEMLOG zmodemlog("startFileData[%s]: %ld\n", ZmSname(info), info->offset) ;#endif // ZMODEMLOG err = ZXmitHdr(ZDATA, ZBIN, info->hdrData+1, info); if(err) { return(err); } return (ZmSendMoreFileData(info));} /* send a chunk of file data in response to a ZRPOS. Whether this * is followed by a ZCRCE, ZCRCG, ZCRCQ or ZCRCW depends on all * sorts of protocol flags */static int ZmSendFileData( ZModem *info ){ info->waitflag = 0 ; return(ZmStartFileData(info));}/* here if an ACK arrived while transmitting data. Update * last known receiver offset, and try to send some more * data. */static int ZmGotSendAck( ZModem *info ){ u_long offset ; offset = ZDec4(info->hdrData+1) ; if( offset > info->lastOffset ) info->lastOffset = offset ;#ifdef ZMODEMLOG zmodemlog("GotSendAck[%s]: %ld\n", ZmSname(info), info->offset) ;#endif // ZMODEMLOG return 0 ; /* DONT send more data, that will happen * later anyway */}/* here if an ACK arrived after last file packet sent. Send * the EOF. */static int ZmGotSendDoneAck( ZModem *info ){ u_long offset ; offset = ZDec4(info->hdrData+1) ; if( offset > info->lastOffset ) info->lastOffset = offset ;#ifdef ZMODEMLOG zmodemlog("GotSendDoneAck[%s]: %ld\n", ZmSname(info), info->offset) ;#endif // info->state = SendEof ; info->timeout = 60 ; return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info) ;} /* off to a bad start; ZDATA header was corrupt. Start * from beginning */static int ZmGotSendNak( ZModem *info ){ info->offset = info->zrposOffset ; ZFileSeek(info->file, info->offset, info); /* TODO: what if fseek fails? Send EOF? */#ifdef ZMODEMLOG zmodemlog("GotSendNak[%s]: %ld\n", ZmSname(info), info->offset) ;#endif return (ZmSendMoreFileData(info));} /* got a ZSKIP, receiver doesn't want this file. */static int ZmSkipFile( ZModem *info ){#ifdef ZMODEMLOG zmodemlog("SkipFile[%s]\n", ZmSname(info)) ;#endif // ZMODEMLOG ZCloseFile(info->file, info); return ZmDone ;} /* got a ZRPOS packet in the middle of sending a file, * set new offset and try again */static int ZmGotSendPos( ZModem *info ){ ZStatus(DataErr, ++info->errCount, NULL) ; info->waitflag = 1 ; /* next pkt should wait, to resync */#ifdef ZMODEMLOG zmodemlog("GotSendPos[%s]\n", ZmSname(info), info->offset) ;#endif // ZMODEMLOG return(ZmStartFileData(info));} /* here if an ACK arrived while waiting while transmitting data. * Update last known receiver offset, and try to send some more * data. */static int ZmGotSendWaitAck( ZModem *info ){ u_long offset ; int err ; offset = ZDec4(info->hdrData+1) ; if( offset > info->lastOffset ) info->lastOffset = offset ;#ifdef ZMODEMLOG zmodemlog("GotSendWaitAck[%s]\n", ZmSname(info), offset) ;#endif // ZMODEMLOG err = ZXmitHdr(ZDATA, ZBIN, ZEnc4(info->offset), info); if(err) return(err); return (ZmSendMoreFileData(info));}static int ZmResendEof( ZModem *info ){ return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info) ;}static int ZmOverAndOut( ZModem *info ){ ZXmitStr((u_char *)"OO", 2, info) ; return ZmDone ;} /* YMODEM */static u_char eotstr[1] = {EOT} ; /* ymodem parser */int YsendChar( char c, ZModem *info ){ int err ; if( info->canCount >= 2 ) { ZStatus(RmtCancel, 0, NULL) ; return ZmErrCancel ; } switch( info->state ) { case YTStart: /* wait for 'G', 'C' or NAK */ switch( c ) { case 'G': /* streaming YModem */ case 'C': /* CRC YModem */ case NAK: /* checksum YModem */ info->PacketType = c ; return ZmDone ; default: return 0 ; } case YTFile: /* sent filename, waiting for ACK or NAK */ switch( c ) { case NAK: /* resend */ case 'C': case 'G': ZStatus(DataErr, ++info->errCount, NULL) ; return YSendFilename(info) ; case ACK: info->state = YTDataWait ; default: return 0 ; } case YTDataWait: /* sent filename, waiting for G,C or NAK */ switch( c ) { case NAK: case 'C': case 'G': info->chrCount = 0 ; if( info->PacketType == 'G' ) /* send it all at once */ { while( info->state == YTData ) { err = YSendData(info); if(err) { return(err); } } return 0 ; } else return YSendData(info) ; default: return 0 ; } case YTData: /* sent data, waiting for ACK or NAK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -