Exemplo n.º 1
0
        /// <summary>
        /// Sends the EOT character.
        /// </summary>
        /// <param name="channel">The channel to send on.</param>
        /// <param name="cancellationToken">Cancellation token to use.</param>
        protected async Task SendEot(Stream channel, CancellationToken cancellationToken)
        {
            int        errorCount = 0;
            ModemTimer timer      = new ModemTimer(BLOCK_TIMEOUT);

            while (errorCount < 10)
            {
                await SendByte(channel, EOT, cancellationToken);

                try
                {
                    int character = await ReadByte(channel, timer, cancellationToken);

                    if (character == ACK)
                    {
                        return;
                    }
                    else if (character == CAN)
                    {
                        throw new IOException("Transmission terminated");
                    }
                }
                catch (TimeoutException)
                {
                    // Ignore timeout exceptions.
                }

                errorCount++;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Reads a byte from the stream.
        /// </summary>
        /// <param name="channel">The channel to read from.</param>
        /// <param name="timer">Max time to wait to read from the buffer.</param>
        /// <param name="cancellationToken">Cancellation token used to cancel the task.</param>
        /// <returns>A single byte.</returns>
        protected async Task <byte> ReadByte(Stream channel, ModemTimer timer, CancellationToken cancellationToken)
        {
            byte?retVal = null;

            // Keep trying to read until we have some data or until it times out.
            while (!timer.Expired && !retVal.HasValue)
            {
                byte[] buffer  = new byte[1];
                int    numRead = await channel.ReadAsync(buffer, 0, 1, cancellationToken);

                if (numRead > 0)
                {
                    retVal = buffer[0];
                }

                Thread.Sleep(10);
            }

            // Error out if we didn't read anything.
            if (!retVal.HasValue)
            {
                throw new TimeoutException();
            }

            return(retVal.Value);
        }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Waits for the receiver request token.
        /// </summary>
        /// <param name="channel">Channel to wait upon.</param>
        /// <param name="timer">Timer to use.</param>
        /// <param name="cancellationToken">Cancellation token to use.</param>
        /// <returns>True if we should continue, false if we should resend.</returns>
        protected async Task <bool> WaitReceiverRequest(Stream channel, ModemTimer timer, CancellationToken cancellationToken)
        {
            bool?retVal = null;

            while (!retVal.HasValue && !timer.Expired) // TODO: Validate this change.
            {
                int character = await ReadByte(channel, timer, cancellationToken);

                if (character == NAK)
                {
                    retVal = false;
                }
                if (character == ST_C)
                {
                    retVal = true;
                }
            }

            return(retVal.Value);
        }
Exemplo n.º 5
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");
        }