protected int BuildHEXHeader(byte[] data, Header hdr) { data[0] = ZPAD; data[1] = ZPAD; data[2] = ZDLE; data[3] = ZHEX; int index = 4; index = PutHex(data, index, hdr.Type); ushort crc = Crc16.Update(Crc16.InitialValue, hdr.Type); index = PutHex(data, index, hdr.ZP0); crc = Crc16.Update(crc, hdr.ZP0); index = PutHex(data, index, hdr.ZP1); crc = Crc16.Update(crc, hdr.ZP1); index = PutHex(data, index, hdr.ZP2); crc = Crc16.Update(crc, hdr.ZP2); index = PutHex(data, index, hdr.ZP3); crc = Crc16.Update(crc, hdr.ZP3); index = PutHex(data, index, (byte)(crc >> 8)); index = PutHex(data, index, (byte)(crc)); data[index++] = CR; data[index++] = LF | 0x80; // sz/rz send 8a instead of 0a if (!(hdr.Type == ZFIN || hdr.Type == ZACK)) { data[index++] = XON; } return(index); }
// ZFILE private void SendZFILE() { if (_stopped) { return; } Header hdr = new Header(ZFILE, zf0: ZCBIN); int pktOutCount = (_txCrcType == CRCType.CRC32) ? BuildBin32Header(_sndBuff, hdr) : BuildBin16Header(_sndBuff, hdr); SendPacket(_sndBuff, pktOutCount); string fn = Path.GetFileName(_fileName); fn = fn.Replace(" ", "_"); string data = fn + '\0' + _fileSize.ToString() + '\0'; byte[] bytes = Encoding.UTF8.GetBytes(data); int index = 0; foreach (byte b in bytes) { index = PutBin(_sndBuff, index, b); } uint crc = (_txCrcType == CRCType.CRC32) ? Crc32.Update(Crc32.InitialValue, bytes, 0, bytes.Length) : Crc16.Update(Crc16.InitialValue, bytes, 0, bytes.Length); _sndBuff[index++] = ZDLE; _sndBuff[index++] = ZCRCW; crc = (_txCrcType == CRCType.CRC32) ? Crc32.Update(crc, ZCRCW) ^ Crc32.XorValue : Crc16.Update((ushort)crc, ZCRCW); if (_txCrcType == CRCType.CRC32) { index = PutCRC32(_sndBuff, index, crc); } else { index = PutCRC16(_sndBuff, index, (ushort)crc); } _sndBuff[index++] = XON; // ZCRCW requires response SendPacket(_sndBuff, index); }
protected int BuildBin16Header(byte[] data, Header hdr) { data[0] = ZPAD; data[1] = ZDLE; data[2] = ZBIN; int index = 3; index = PutBin(data, index, hdr.Type); ushort crc = Crc16.Update(Crc16.InitialValue, hdr.Type); index = PutBin(data, index, hdr.ZP0); crc = Crc16.Update(crc, hdr.ZP0); index = PutBin(data, index, hdr.ZP1); crc = Crc16.Update(crc, hdr.ZP1); index = PutBin(data, index, hdr.ZP2); crc = Crc16.Update(crc, hdr.ZP2); index = PutBin(data, index, hdr.ZP3); crc = Crc16.Update(crc, hdr.ZP3); index = PutCRC16(data, index, crc); return(index); }
private bool CheckCRC(CRCType crcType, byte[] data, int len) { if (crcType == CRCType.CRC32) { uint crc = Crc32.Update(Crc32.InitialValue, data, 0, len - 4) ^ Crc32.XorValue; //Debug.WriteLine("CRC32: {0:x8}", crc); uint crcfld = (((uint)data[len - 4]) | ((uint)data[len - 3] << 8) | ((uint)data[len - 2] << 16) | ((uint)data[len - 1] << 24)); return(crc == crcfld); } else { // CRC16 ushort crc = Crc16.Update(Crc16.InitialValue, data, 0, len - 2); //Debug.WriteLine("CRC16: {0:x4}", crc); ushort crcfld = (ushort)((data[len - 2] << 8) | data[len - 1]); return(crc == crcfld); } }
private void SendBlock(bool useCrc, bool resend) { if (_input == null || _fileClosed) { return; } if (resend) { Trace("Seek to {0}", _prevPos); _input.Seek(_prevPos, SeekOrigin.Begin); } else { _prevPos = _nextPos; _sequenceNumber++; } int dataLength; if (useCrc) { dataLength = (_fileSize - _prevPos < 1024L) ? 128 : 1024; } else { dataLength = 128; } int readLen = _input.Read(_sendBuff, 3, dataLength); _nextPos = _input.Position; if (readLen == 0) { _state = State.AfterEOT; Trace("<-- EOT"); Send(EOT); return; } _sendBuff[0] = (dataLength == 1024) ? STX : SOH; _sendBuff[1] = _sequenceNumber; _sendBuff[2] = (byte)(255 - _sequenceNumber); for (int i = 3 + readLen; i < 3 + dataLength; ++i) { _sendBuff[i] = CPMEOF; } int blockLen = 3 + dataLength; if (useCrc) { ushort crc = Crc16.Update(Crc16.InitialValue, _sendBuff, 3, dataLength); _sendBuff[blockLen++] = (byte)(crc >> 8); _sendBuff[blockLen++] = (byte)crc; } else { byte checksum = 0; for (int i = 3; i < 3 + dataLength; ++i) { checksum += _sendBuff[i]; } _sendBuff[blockLen++] = checksum; } Trace("<-- {0:X2} {1:X2} ...({2})", _sendBuff[0], _sendBuff[1], blockLen); Send(_sendBuff, blockLen); SetProgressValue((int)_nextPos, (int)_fileSize); }
public override void OnReception(ByteDataFragment fragment) { Interlocked.Exchange(ref _lastReceptionTimeUtcTicks, DateTime.UtcNow.Ticks); if (_aborting) { return; } byte[] data = fragment.Buffer; int offset = fragment.Offset; int length = fragment.Length; BlockTypeInfo blockInfo; if (_recvLen > 0) { blockInfo = GetBlockTypeInfo(_recvBuff[0], Volatile.Read(ref _mode)); } else { blockInfo = new BlockTypeInfo(); // update later } for (int i = 0; i < length; i++) { byte c = data[offset + i]; if (_recvLen == 0) { if (c == EOT) { Trace("--> EOT"); FlushPendingBuffer(true); Trace("<-- ACK"); Send(ACK); Completed(false, true, XZModemPlugin.Instance.Strings.GetString("Message.XModem.ReceiveComplete")); return; } if (c != SOH && c != STX) { continue; // skip } // determine expected block type blockInfo = GetBlockTypeInfo(c, Volatile.Read(ref _mode)); } _recvBuff[_recvLen++] = c; if (_recvLen >= blockInfo.BlockSize) { goto BlockReceived; } } return; BlockReceived: // a block has been received Interlocked.Exchange(ref _lastBlockTimeUtcTicks, DateTime.UtcNow.Ticks); Trace("--> {0:X2} {1:X2} ...({2})", _recvBuff[0], _recvBuff[1], _recvLen); // check sequence number if (_recvBuff[1] != _nextSequenceNumber || _recvBuff[2] != (255 - _nextSequenceNumber)) { Trace("<-- NAK (bad seq)"); goto Error; } // check CRC or checksum if (blockInfo.HasCRC) { ushort crc = Crc16.Update(Crc16.InitialValue, _recvBuff, blockInfo.DataOffset, blockInfo.DataLength); int crcIndex = blockInfo.DataOffset + blockInfo.DataLength; if (_recvBuff[crcIndex] != (byte)(crc >> 8) || _recvBuff[crcIndex + 1] != (byte)crc) { // CRC error Trace("<-- NAK (CRC error)"); goto Error; } } else { byte checksum = 0; int index = blockInfo.DataOffset; for (int n = 0; n < blockInfo.DataLength; ++n) { checksum += _recvBuff[index++]; } if (_recvBuff[index] != checksum) { // checksum error Trace("<-- NAK (checksum error)"); goto Error; } } // ok _nextSequenceNumber++; FlushPendingBuffer(false); SaveToPendingBuffer(_recvBuff, blockInfo.DataOffset, blockInfo.DataLength); _errorCount = 0; _recvLen = 0; Send(ACK); return; Error: _recvLen = 0; _errorCount++; if (_errorCount > MAX_ERROR) { Abort(XZModemPlugin.Instance.Strings.GetString("Message.XModem.CouldNotReceiveCorrectData"), false); } else { Send(NAK); } }
// ZDATA private void SendZDATA(CancellationToken cancelToken) { Restart: uint filePos = Volatile.Read(ref _filePosReq); Volatile.Write(ref _filePosReqChanged, false); _fileStream.Seek(filePos, SeekOrigin.Begin); // Header Header hdr = new Header(ZDATA, pos: filePos); int pktOutCount = (_txCrcType == CRCType.CRC32) ? BuildBin32Header(_sndBuff, hdr) : BuildBin16Header(_sndBuff, hdr); SendPacket(_sndBuff, pktOutCount); // Sub frames while (!cancelToken.IsCancellationRequested) { if (Volatile.Read(ref _filePosReqChanged)) { goto Restart; } uint crc = (_txCrcType == CRCType.CRC32) ? Crc32.InitialValue : Crc16.InitialValue; int index = 0; int len = (int)Math.Min(_fileSize - filePos, (long)_frameSize); for (int i = 0; i < len; ++i) { int c = _fileStream.ReadByte(); if (c < 0) { break; } filePos++; byte b = (byte)c; index = PutBin(_sndBuff, index, b); crc = (_txCrcType == CRCType.CRC32) ? Crc32.Update(crc, b) : Crc16.Update((ushort)crc, b); } byte frameType = (filePos >= _fileSize) ? ZCRCE : ZCRCG; _sndBuff[index++] = ZDLE; _sndBuff[index++] = frameType; crc = (_txCrcType == CRCType.CRC32) ? Crc32.Update(crc, frameType) ^ Crc32.XorValue : Crc16.Update((ushort)crc, frameType); if (_txCrcType == CRCType.CRC32) { index = PutCRC32(_sndBuff, index, crc); } else { index = PutCRC16(_sndBuff, index, (ushort)crc); } //Debug.WriteLine("frameType = {0:x2}", frameType); //Debug.WriteLine("CRC = {0:x8}", crc); SendPacket(_sndBuff, index); if (!_stopped) { _parent.SetProgressValue(filePos); } if (frameType == ZCRCE) { break; } Thread.Sleep(0); } // ZEOF int zeofCount = BuildHEXHeader(_sndBuff, new Header(ZEOF, pos: filePos)); SendPacket(_sndBuff, zeofCount); }