Skip to content

Commit

Permalink
fix file read error condition, file CRC/hash
Browse files Browse the repository at this point in the history
  • Loading branch information
ctacke authored and CartBlanche committed Sep 29, 2023
1 parent 4f8d5c8 commit 7af0825
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,14 @@ protected override async ValueTask ExecuteCommand(IMeadowConnection connection,
// the connection passes messages back to us (info about actions happening on-device
connection.DeviceMessageReceived += (s, e) =>
{
Logger.LogInformation(e.message);
if (e.message.Contains("% downloaded"))
{
// don't echo this, as we're already reporting % written
}
else
{
Logger.LogInformation(e.message);
}
};

var package = await GetSelectedPackage();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Diagnostics;

namespace Meadow.Hcom
{
Expand Down Expand Up @@ -230,8 +229,7 @@ private async Task ListenerProc()
_readFileInfo.FileStream = File.Create(_readFileInfo.LocalFileName);

var uploadRequest = RequestBuilder.Build<StartFileDataRequest>();
EncodeAndSendPacket(uploadRequest.Serialize());
// (this as IMeadowConnection).EnqueueRequest(uploadRequest);
await EncodeAndSendPacket(uploadRequest.Serialize());
}
else if (response is UploadDataPacketResponse udp)
{
Expand Down Expand Up @@ -318,8 +316,8 @@ private async Task ListenerProc()
}
catch (Exception ex)
{
RaiseConnectionError(ex);
Debug.WriteLine($"listen error {ex.Message}");
_logger?.LogTrace(ex, "An error occurred while listening to the serial port.");
await Task.Delay(1000);
}
}
Expand Down
51 changes: 38 additions & 13 deletions Source/v2/Meadow.Hcom/Connections/SerialConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Buffers;
using System.Diagnostics;
using System.IO.Ports;
using System.Security.Cryptography;
using System.Text;

namespace Meadow.Hcom;

Expand Down Expand Up @@ -931,10 +933,28 @@ private async Task<bool> WriteFile(
CancellationToken? cancellationToken = null)
{
var command = RequestBuilder.Build<InitFileWriteRequest>();

var fileBytes = File.ReadAllBytes(localFileName);

var fileHash = Encoding.ASCII.GetBytes("12345678901234567890123456789012"); // must be 32 bytes
if (writeAddress != 0)
{
// calculate the MD5 hash of the file - we have to send it as a UTF8 string, not as bytes.
using var md5 = MD5.Create();
var hashBytes = md5.ComputeHash(fileBytes);
var hashString = BitConverter.ToString(hashBytes)
.Replace("-", "")
.ToLowerInvariant();
fileHash = Encoding.UTF8.GetBytes(hashString);
}
var fileCrc = NuttxCrc.Crc32part(fileBytes, (uint)fileBytes.Length, 0);

command.SetParameters(
localFileName,
meadowFileName ?? Path.GetFileName(localFileName),
fileCrc,
writeAddress,
fileHash,
initialRequestType);

var accepted = false;
Expand Down Expand Up @@ -967,21 +987,21 @@ void OnFileError(object? sender, Exception exception)
}

// now send the file data

using FileStream fs = File.OpenRead(localFileName);

// The maximum data bytes is max packet size - 2 bytes for the sequence number
byte[] packet = new byte[Protocol.HCOM_PROTOCOL_PACKET_MAX_SIZE - 2];
int bytesRead;
ushort sequenceNumber = 0;

var progress = 0;
var expected = fs.Length;
var expected = fileBytes.Length;

var fileName = Path.GetFileName(localFileName);

base.RaiseFileWriteProgress(fileName, progress, expected);

var oldTimeout = _port.ReadTimeout;
_port.ReadTimeout = 60000;

while (true)
{
if (cancellationToken.HasValue && cancellationToken.Value.IsCancellationRequested)
Expand All @@ -991,15 +1011,20 @@ void OnFileError(object? sender, Exception exception)

sequenceNumber++;

// sequence number at the start of the packet
Array.Copy(BitConverter.GetBytes(sequenceNumber), packet, 2);
// followed by the file data
bytesRead = fs.Read(packet, 2, packet.Length - 2);
if (bytesRead <= 0) break;
await EncodeAndSendPacket(packet, bytesRead + 2, cancellationToken);
progress += bytesRead;

var toRead = fileBytes.Length - progress;
if (toRead > packet.Length - 2)
{
toRead = packet.Length - 2;
}
Array.Copy(fileBytes, progress, packet, 2, toRead);
await EncodeAndSendPacket(packet, toRead + 2, cancellationToken);
progress += toRead;
base.RaiseFileWriteProgress(fileName, progress, expected);
if (progress >= fileBytes.Length) break;
}
_port.ReadTimeout = oldTimeout;

base.RaiseFileWriteProgress(fileName, expected, expected);

Expand Down Expand Up @@ -1035,21 +1060,21 @@ void OnFileError(object? sender, Exception exception)
{
FileReadCompleted += OnFileReadCompleted;
FileException += OnFileError;
ConnectionError += OnFileError;

EnqueueRequest(command);

if (!await WaitForResult(
() =>
{
if (ex != null) throw ex;
return completed;
return completed | ex != null;
},
cancellationToken))
{
return false;
}

return true;
return ex == null;
}
finally
{
Expand Down
11 changes: 7 additions & 4 deletions Source/v2/Meadow.Hcom/Serial Requests/InitFileWriteRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,13 @@ internal class InitFileWriteRequest : Request
public void SetParameters(
string localFile,
string meadowFileName,
int espAddress = 0,
uint fileCrc,
int espAddress,
byte[] espHash,
RequestType requestType = RequestType.HCOM_MDOW_REQUEST_START_FILE_TRANSFER)
{
if (espHash.Length != 32) throw new ArgumentException();

// file write has additional header payload that's sent with the request, build it here
_requestType = requestType;

Expand All @@ -97,13 +101,12 @@ public void SetParameters(
MeadowFileName = meadowFileName;

var nameBytes = Encoding.ASCII.GetBytes(meadowFileName);
var espHash = Encoding.ASCII.GetBytes("12345678901234567890123456789012"); // Must be 32 bytes

Payload = new byte[4 + 4 + 4 + 32 + nameBytes.Length];
Array.Copy(BitConverter.GetBytes((uint)source.Length), 0, Payload, 0, 4); // file size
Array.Copy(BitConverter.GetBytes((uint)source.Length), 0, Payload, 4, 4); // file crc
Array.Copy(BitConverter.GetBytes(fileCrc), 0, Payload, 4, 4); // file crc
Array.Copy(BitConverter.GetBytes(espAddress), 0, Payload, 8, 4); // ESP flash address offset
Array.Copy(espHash, 0, Payload, 12, espHash.Length); // TODO: ESP hash (dev note: this appears to never be used or needed?)
Array.Copy(espHash, 0, Payload, 12, espHash.Length);
Array.Copy(nameBytes, 0, Payload, 44, nameBytes.Length); // file name
}
}

0 comments on commit 7af0825

Please sign in to comment.