zmodemr.c
来自「Gcomm is a serial communications program」· C语言 代码 · 共 751 行 · 第 1/2 页
C
751 行
ResendCrcReq(ZModem *info){ zmodemlog("ResendCrcReq[%s]: send ZCRC\n", sname(info)) ; return ZXmitHdrHex(ZCRC, zeros, info) ;} /* received file CRC, now we're ready to accept or reject */static intGotFileCrc( register ZModem *info ){ zmodemlog("GotFileCrc[%s]: call requestFile\n", sname(info)) ; return requestFile(info, ZDec4(info->hdrData+1)) ;} /* last ZRPOS was bad, resend it */intResendRpos( register ZModem *info ){ zmodemlog("ResendRpos[%s]: send ZRPOS(%ld)\n", sname(info), info->offset) ; return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ;} /* recevied ZDATA header */static intGotData( register ZModem *info ){ int err ; zmodemlog("GotData[%s]:\n", sname(info)) ; if( ZDec4(info->hdrData+1) != info->offset ) { if( info->attn != NULL && (err=ZAttn(info)) != 0 ) return err ; zmodemlog(" bad, send ZRPOS(%ld)\n", info->offset); return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info) ; } /* Let's do it! */ zmodemlog(" call dataSetup\n"); return dataSetup(info) ;} /* Utility: flush input, send attn, send specified header */static intfileError( register ZModem *info, int type, int data ){ int err ; info->InputState = Idle ; info->chrCount=0 ; if( info->attn != NULL && (err=ZAttn(info)) != 0 ) return err ; return ZXmitHdrHex(type, ZEnc4(data), info) ;} /* received file data */intGotFileData( register ZModem *info, int crcGood ){ /* OK, now what? Fushing the buffers and executing the * attn sequence has likely chopped off the input stream * mid-packet. Now we switch to idle mode and treat all * incoming stuff like noise until we get a new valid * packet. */ if( !crcGood ) { /* oh bugger, an error. */ zmodemlog( "GotFileData[%s]: bad crc, send ZRPOS(%ld), new state = RFile\n", sname(info), info->offset) ; ZStatus(DataErr, ++info->errCount, NULL) ; if( info->errCount > MaxErrs ) { ZmodemAbort(info) ; return ZmDataErr ; } else { info->state = RFile ; info->InputState = Idle ; info->chrCount=0 ; return fileError(info, ZRPOS, info->offset) ; } } if( ZWriteFile(info->buffer, info->chrCount, info->file, info) ) { /* RED ALERT! Could not write the file. */ ZStatus(FileErr, errno, NULL) ; info->state = RFinish ; info->InputState = Idle ; info->chrCount=0 ; return fileError(info, ZFERR, errno) ; } zmodemlog("GotFileData[%s]: %ld.%d,", sname(info), info->offset, info->chrCount) ; info->offset += info->chrCount ; ZStatus(RcvByteCount, info->offset, NULL) ; /* if this was the last data subpacket, leave data mode */ if( info->PacketType == ZCRCE || info->PacketType == ZCRCW ) { zmodemlog(" ZCRCE|ZCRCW, new state RFile") ; info->state = RFile ; info->InputState = Idle ; info->chrCount=0 ; } else { zmodemlog(" call dataSetup") ; (void) dataSetup(info) ; } if( info->PacketType == ZCRCQ || info->PacketType == ZCRCW ) { zmodemlog(", send ZACK\n") ; return ZXmitHdrHex(ZACK, ZEnc4(info->offset), info) ; } else zmodemlog("\n") ; return 0 ;} /* received ZEOF packet, file is now complete */static intGotEof( register ZModem *info ){ zmodemlog("GotEof[%s]: offset=%ld\n", sname(info), info->offset) ; if( ZDec4(info->hdrData+1) != info->offset ) { zmodemlog(" bad length, state = RFile\n") ; info->state = RFile ; return 0 ; /* it was probably spurious */ } /* TODO: if we can't close the file, send a ZFERR */ ZCloseFile(info) ; info->file = NULL ; ZStatus(FileEnd, 0, info->filename) ; if( info->filename != NULL ) { free(info->filename) ; info->filename = NULL ; } return SendRinit(info) ;} /* got ZFIN, respond in kind */static intGotFin( register ZModem *info ){ zmodemlog("GotFin[%s]: send ZFIN\n", sname(info)) ; info->InputState = Finish ; info->chrCount = 0 ; if( info->filename != NULL ) free(info->filename) ; return ZXmitHdrHex(ZFIN, zeros, info) ;}static intGotFreecnt( register ZModem *info ){ /* TODO: how do we find free space on system? */ return ZXmitHdrHex(ZACK, ZEnc4(0xffffffff), info) ;} /* YMODEM */static u_char AckStr[1] = {ACK} ;static u_char NakStr[1] = {NAK} ;static u_char CanStr[2] = {CAN,CAN} ;static int ProcessPacket() ;static int acceptPacket() ;static int rejectPacket() ;static int calcCrc() ;intYrcvChar( char c, register ZModem *info ){ int err ; if( info->canCount >= 2 ) { ZStatus(RmtCancel, 0, NULL) ; return ZmErrCancel ; } switch( info->state ) { case YREOF: if( c == EOT ) { ZCloseFile(info) ; info->file = NULL ; ZStatus(FileEnd, 0, info->filename) ; if( info->filename != NULL ) free(info->filename) ; if( (err = acceptPacket(info)) != 0 ) return err ; info->packetCount = -1 ; info->offset = 0 ; info->state = YRStart ; return ZXmitStr((u_char *)"C", 1, info) ; } /* else, drop through */ case YRStart: case YRDataWait: switch( c ) { case SOH: case STX: info->pktLen = c == SOH ? (128+4) : (1024+4) ; info->state = YRData ; info->chrCount = 0 ; info->timeout = 1 ; info->noiseCount = 0 ; info->crc = 0 ; break ; case EOT: /* ignore first EOT to protect against false eot */ info->state = YREOF ; return rejectPacket(info) ; default: if( ++info->noiseCount > 135 ) return ZXmitStr(NakStr, 1, info) ; break ; } break ; case YRData: info->buffer[info->chrCount++] = c ; if( info->chrCount >= info->pktLen ) return ProcessPacket(info) ; break ; default: break ; } return 0 ;}intYrcvTimeout( register ZModem *info ){ switch( info->state ) { case YRStart: if( info->timeoutCount >= 10 ) { (void) ZXmitStr(CanStr, 2, info) ; return ZmErrInitTo ; } return ZXmitStr((u_char *)"C", 1, info) ; case YRDataWait: case YREOF: case YRData: if( info->timeoutCount >= 10 ) { (void) ZXmitStr(CanStr, 2, info) ; return ZmErrRcvTo ; } return ZXmitStr(NakStr, 1, info) ; default: return 0 ; }}static intProcessPacket( register ZModem *info ){ int idx = (u_char) info->buffer[0] ; int idxc = (u_char) info->buffer[1] ; int crc0, crc1 ; int err ; info->state = YRDataWait ; if( idxc != 255 - idx ) { ZStatus(DataErr, ++info->errCount, NULL) ; return rejectPacket(info) ; } if( idx == (info->packetCount%256) ) /* quietly ignore dup */ return acceptPacket(info) ; if( idx != (info->packetCount+1)%256 ) { /* out of sequence */ (void) ZXmitStr(CanStr, 2, info) ; return ZmErrSequence ; } crc0 = (u_char)info->buffer[info->pktLen-2] << 8 | (u_char)info->buffer[info->pktLen-1] ; crc1 = calcCrc(info->buffer+2, info->pktLen-4) ; if( crc0 != crc1 ) { ZStatus(DataErr, ++info->errCount, NULL) ; return rejectPacket(info) ; } ++info->packetCount ; if( info->packetCount == 0 ) /* packet 0 is filename */ { if( info->buffer[2] == '\0' ) { /* null filename is FIN */ (void) acceptPacket(info) ; return ZmDone ; } parseFileName(info, (char *)info->buffer+2) ; info->file = ZOpenFile(info->filename, 0, info) ; if( info->file == NULL ) { (void) ZXmitStr(CanStr, 2, info) ; return ZmErrCantOpen ; } if( (err = acceptPacket(info)) != 0 ) return err ; return ZXmitStr((u_char *)"C", 1, info) ; } if( ZWriteFile(info->buffer+2, info->pktLen-4, info->file, info) ) { ZStatus(FileErr, errno, NULL) ; (void) ZXmitStr(CanStr, 2, info) ; return ZmErrSys ; } info->offset += info->pktLen-4 ; ZStatus(RcvByteCount, info->offset, NULL) ; (void) acceptPacket(info) ; return 0 ;}static intrejectPacket( register ZModem *info ){ info->timeout = 10 ; return ZXmitStr(NakStr, 1, info) ;}static intacceptPacket( register ZModem *info ){ info->state = YRDataWait ; info->timeout = 10 ; return ZXmitStr(AckStr, 1, info) ;}static intcalcCrc( u_char *str, int len ){ int crc = 0 ; while( --len >= 0 ) crc = updcrc(*str++, crc) ; crc = updcrc(0,crc) ; crc = updcrc(0,crc) ; return crc & 0xffff ;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?