コード例 #1
0
        /// <summary>
        /// Transfers a file using Y Modem.
        /// </summary>
        /// <param name="stream">The stream to perform the transfer on.</param>
        /// <param name="dataStream">The datastream to transfer.</param>
        /// <param name="fileName">The name of the file to transfer.</param>
        /// <param name="cancellationToken">Cancellation token for cancelling the task.</param>
        public override async Task Send(Stream channel, Stream dataStream, string fileName, CancellationToken cancellationToken)
        {
            // Setup the timer.
            ModemTimer timer = new ModemTimer(WAIT_FOR_RECEIVER_TIMEOUT);

            timer.Start();

            // Choose a CRC calculation.
            bool useCrc16 = await WaitReceiverRequest(channel, timer, cancellationToken);

            ICrc crc = await WaitReceiverRequest(channel, timer, cancellationToken) ? Crc.Crc16 : Crc.Crc8;

            // Convert the filename to bytes.
            string fileNameString = $"{fileName.ToLower()}";

            byte[] fileNameBytes = new byte[128];
            Encoding.UTF8.GetBytes(fileNameString, 0, fileNameString.Length, fileNameBytes, 0);

            // Send the filename block.
            await SendBlock(channel, 0, fileNameBytes, 128, crc, cancellationToken);

            // Wait till the device says it's good.
            await WaitReceiverRequest(channel, timer, cancellationToken);

            // Send the file contents.
            await SendBlocks(channel, dataStream, 1, crc, cancellationToken);

            // Send the EOT (we're done sending data) character.
            await SendEot(channel, cancellationToken);
        }
コード例 #2
0
        /// <summary>
        /// Sends a block of data.
        /// </summary>
        /// <param name="channel">Channel to send the data on.</param>
        /// <param name="blockNumber">The block number we're sending.</param>
        /// <param name="block">The block contents to send.</param>
        /// <param name="dataLength">The length of the block.</param>
        /// <param name="crc">CRC calculation to use.</param>
        /// <param name="cancellationToken">Cancellation token to use.</param>
        protected async Task SendBlock(Stream channel, int blockNumber, byte[] block, int dataLength, ICrc crc, CancellationToken cancellationToken)
        {
            ModemTimer timer      = new ModemTimer(SEND_BLOCK_TIMEOUT);
            int        errorCount = 0;

            if (dataLength < block.Length)
            {
                for (int k = dataLength; k < block.Length; k++)
                {
                    block[k] = CPMEOF;
                }
            }

            while (errorCount < MAXERRORS)
            {
                bool keepGoing = true;

                timer.Start();

                if (block.Length == 1024)
                {
                    channel.WriteByte(STX);
                }
                else //128
                {
                    channel.WriteByte(SOH);
                }

                channel.WriteByte((byte)blockNumber);
                channel.WriteByte((byte)~blockNumber);

                channel.Write(block, 0, block.Length);
                WriteCrc(channel, block, crc);
                channel.Flush();

                while (keepGoing)
                {
                    try
                    {
                        byte character = await ReadByte(channel, timer, cancellationToken);

                        if (character == ACK)
                        {
                            return;
                        }
                        else if (character == NAK)
                        {
                            errorCount++;
                            keepGoing = false;
                        }
                        else if (character == CAN)
                        {
                            throw new IOException("Transmission terminated");
                        }
                    }
                    catch (TimeoutException)
                    {
                        errorCount++;
                        keepGoing = false;
                    }
                }
            }

            throw new IOException("Too many errors caught, abandoning transfer");
        }