private bool DecodeAndProcessPacket(Memory <byte> packetBuffer, CancellationToken cancellationToken) { var decodedBuffer = ArrayPool <byte> .Shared.Rent(MeadowDeviceManager.MaxAllowableMsgPacketLength); var packetLength = packetBuffer.Length; // It's possible that we may find a series of 0x00 values in the buffer. // This is because when the sender is blocked (because this code isn't // running) it will attempt to send a single 0x00 before the full message. // This allows it to test for a connection. When the connection is // unblocked this 0x00 is sent and gets put into the buffer along with // any others that were queued along the usb serial pipe line. if (packetLength == 1) { //_logger.LogTrace("Throwing out 0x00 from buffer"); return(false); } var decodedSize = CobsTools.CobsDecoding(packetBuffer, ref decodedBuffer); // If a message is too short it is ignored if (decodedSize < MeadowDeviceManager.ProtocolHeaderSize) { return(false); } Debug.Assert(decodedSize <= MeadowDeviceManager.MaxAllowableMsgPacketLength); // Process the received packet ParseAndProcessReceivedPacket(decodedBuffer.AsSpan(0, decodedSize).ToArray(), cancellationToken); ArrayPool <byte> .Shared.Return(decodedBuffer); return(true); }
private async Task EncodeAndSendPacket(byte[] messageBytes, int messageOffset, int messageSize, CancellationToken cancellationToken) { try { // For testing calculate the crc including the sequence number _packetCrc32 = CrcTools.Crc32part(messageBytes, messageSize, 0, _packetCrc32); // Add 2, first to account for start delimiter and second for end byte[] encodedBytes = new byte[MeadowDeviceManager.MaxEstimatedSizeOfEncodedPayload + 2]; // Skip first byte so it can be a start delimiter int encodedToSend = CobsTools.CobsEncoding( messageBytes, messageOffset, messageSize, ref encodedBytes, 1); // Verify COBS - any delimiters left? Skip first byte for (int i = 1; i < encodedToSend; i++) { if (encodedBytes[i] == 0x00) { throw new InvalidProgramException( "All zeros should have been removed. There's one at offset of {i}"); } } // Terminate packet with delimiter so packet boundaries can be more easily found encodedBytes[0] = 0; // Start delimiter encodedToSend++; encodedBytes[encodedToSend] = 0; // End delimiter encodedToSend++; try { using var cts = new CancellationTokenSource(DefaultTimeout); cts.Token.Register(() => throw new TimeoutException("Timeout while writing to serial port")); var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token); await WriteAsync(encodedBytes, encodedToSend, combinedCts.Token) .ConfigureAwait(false); } catch (InvalidOperationException ioe) // Port not opened { Logger.LogError(ioe, "Write but port not opened"); throw; } catch (ArgumentOutOfRangeException aore) // offset or count don't match buffer { Logger.LogError(aore, "Write buffer, offset and count don't line up"); throw; } catch (ArgumentException ae) // offset plus count > buffer length { Logger.LogError(ae, "Write offset plus count > buffer length"); throw; } catch (TimeoutException te) // Took too long to send { Logger.LogError(te, "Write took too long to send"); throw; } } catch (Exception except) { Logger.LogTrace(except, "EncodeAndSendPacket threw"); throw; } }