Files
git.stella-ops.org/src/__Libraries/StellaOps.Router.Transport.Udp/UdpFrameProtocol.cs
StellaOps Bot 6a299d231f
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Add unit tests for Router configuration and transport layers
- Implemented tests for RouterConfig, RoutingOptions, StaticInstanceConfig, and RouterConfigOptions to ensure default values are set correctly.
- Added tests for RouterConfigProvider to validate configurations and ensure defaults are returned when no file is specified.
- Created tests for ConfigValidationResult to check success and error scenarios.
- Developed tests for ServiceCollectionExtensions to verify service registration for RouterConfig.
- Introduced UdpTransportTests to validate serialization, connection, request-response, and error handling in UDP transport.
- Added scripts for signing authority gaps and hashing DevPortal SDK snippets.
2025-12-05 08:01:47 +02:00

80 lines
2.5 KiB
C#

using StellaOps.Router.Common.Enums;
using StellaOps.Router.Common.Models;
namespace StellaOps.Router.Transport.Udp;
/// <summary>
/// Handles serialization and deserialization of frames for UDP transport.
/// Frame format: [1-byte frame type][16-byte correlation GUID][remaining data]
/// </summary>
public static class UdpFrameProtocol
{
private const int FrameTypeSize = 1;
private const int CorrelationIdSize = 16;
private const int HeaderSize = FrameTypeSize + CorrelationIdSize;
/// <summary>
/// Parses a frame from a datagram.
/// </summary>
/// <param name="data">The datagram data.</param>
/// <returns>The parsed frame.</returns>
/// <exception cref="InvalidOperationException">Thrown when the datagram is too small.</exception>
public static Frame ParseFrame(ReadOnlySpan<byte> data)
{
if (data.Length < HeaderSize)
{
throw new InvalidOperationException(
$"Datagram too small: {data.Length} bytes, minimum is {HeaderSize}");
}
var frameType = (FrameType)data[0];
var correlationId = new Guid(data.Slice(FrameTypeSize, CorrelationIdSize));
var payload = data.Length > HeaderSize
? data[HeaderSize..].ToArray()
: Array.Empty<byte>();
return new Frame
{
Type = frameType,
CorrelationId = correlationId.ToString("N"),
Payload = payload
};
}
/// <summary>
/// Serializes a frame to a datagram.
/// </summary>
/// <param name="frame">The frame to serialize.</param>
/// <returns>The serialized datagram bytes.</returns>
public static byte[] SerializeFrame(Frame frame)
{
// Parse or generate correlation ID
var correlationGuid = frame.CorrelationId is not null &&
Guid.TryParse(frame.CorrelationId, out var parsed)
? parsed
: Guid.NewGuid();
var payloadLength = frame.Payload.Length;
var buffer = new byte[HeaderSize + payloadLength];
// Write frame type
buffer[0] = (byte)frame.Type;
// Write correlation ID
correlationGuid.TryWriteBytes(buffer.AsSpan(FrameTypeSize, CorrelationIdSize));
// Write payload
if (payloadLength > 0)
{
frame.Payload.Span.CopyTo(buffer.AsSpan(HeaderSize));
}
return buffer;
}
/// <summary>
/// Gets the header size for UDP frames.
/// </summary>
public static int GetHeaderSize() => HeaderSize;
}